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 . m - the number of rows 1522 . idxm - the global indices of the rows 1523 . n - the number of columns 1524 . idxn - the global indices of the columns 1525 . v - a logically two-dimensional array of values 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 in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 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 . ism - the rows to provide 1618 . isn - the columns to provide 1619 . v - a logically two-dimensional array of values 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 in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 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 . m - the number of block rows 2018 . idxm - the global block indices 2019 . n - the number of block columns 2020 . idxn - the global block indices 2021 . v - a logically two-dimensional array of values 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 stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2040 2041 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2042 options cannot be mixed without intervening calls to the assembly 2043 routines. 2044 2045 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2046 as well as in C. 2047 2048 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2049 simply ignored. This allows easily inserting element stiffness matrices 2050 with homogeneous Dirichlet boundary conditions that you don't want represented 2051 in the matrix. 2052 2053 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2054 internal searching must be done to determine where to place the 2055 data in the matrix storage space. By instead inserting blocks of 2056 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2057 reduced. 2058 2059 Example: 2060 .vb 2061 Suppose m=n=2 and block size(bs) = 2 The array is 2062 2063 1 2 | 3 4 2064 5 6 | 7 8 2065 - - - | - - - 2066 9 10 | 11 12 2067 13 14 | 15 16 2068 2069 v[] should be passed in like 2070 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2071 2072 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2073 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2074 .ve 2075 2076 Fortran Notes: 2077 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2078 .vb 2079 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2080 .ve 2081 2082 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2083 2084 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2085 @*/ 2086 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2087 { 2088 PetscFunctionBeginHot; 2089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2090 PetscValidType(mat, 1); 2091 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2092 PetscAssertPointer(idxm, 3); 2093 PetscAssertPointer(idxn, 5); 2094 MatCheckPreallocated(mat, 1); 2095 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2096 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2097 if (PetscDefined(USE_DEBUG)) { 2098 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2099 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2100 } 2101 if (PetscDefined(USE_DEBUG)) { 2102 PetscInt rbs, cbs, M, N, i; 2103 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2104 PetscCall(MatGetSize(mat, &M, &N)); 2105 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); 2106 for (i = 0; i < n; i++) 2107 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); 2108 } 2109 if (mat->assembled) { 2110 mat->was_assembled = PETSC_TRUE; 2111 mat->assembled = PETSC_FALSE; 2112 } 2113 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2114 if (mat->ops->setvaluesblocked) { 2115 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2116 } else { 2117 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2118 PetscInt i, j, bs, cbs; 2119 2120 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2121 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2122 iidxm = buf; 2123 iidxn = buf + m * bs; 2124 } else { 2125 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2126 iidxm = bufr; 2127 iidxn = bufc; 2128 } 2129 for (i = 0; i < m; i++) { 2130 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2131 } 2132 if (m != n || bs != cbs || idxm != idxn) { 2133 for (i = 0; i < n; i++) { 2134 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2135 } 2136 } else iidxn = iidxm; 2137 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2138 PetscCall(PetscFree2(bufr, bufc)); 2139 } 2140 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2141 PetscFunctionReturn(PETSC_SUCCESS); 2142 } 2143 2144 /*@ 2145 MatGetValues - Gets a block of local values from a matrix. 2146 2147 Not Collective; can only return values that are owned by the give process 2148 2149 Input Parameters: 2150 + mat - the matrix 2151 . v - a logically two-dimensional array for storing the values 2152 . m - the number of rows 2153 . idxm - the global indices of the rows 2154 . n - the number of columns 2155 - idxn - the global indices of the columns 2156 2157 Level: advanced 2158 2159 Notes: 2160 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2161 The values, `v`, are then returned in a row-oriented format, 2162 analogous to that used by default in `MatSetValues()`. 2163 2164 `MatGetValues()` uses 0-based row and column numbers in 2165 Fortran as well as in C. 2166 2167 `MatGetValues()` requires that the matrix has been assembled 2168 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2169 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2170 without intermediate matrix assembly. 2171 2172 Negative row or column indices will be ignored and those locations in `v` will be 2173 left unchanged. 2174 2175 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2176 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2177 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2178 2179 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2180 @*/ 2181 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2182 { 2183 PetscFunctionBegin; 2184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2185 PetscValidType(mat, 1); 2186 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2187 PetscAssertPointer(idxm, 3); 2188 PetscAssertPointer(idxn, 5); 2189 PetscAssertPointer(v, 6); 2190 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2191 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2192 MatCheckPreallocated(mat, 1); 2193 2194 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2195 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2196 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2197 PetscFunctionReturn(PETSC_SUCCESS); 2198 } 2199 2200 /*@ 2201 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2202 defined previously by `MatSetLocalToGlobalMapping()` 2203 2204 Not Collective 2205 2206 Input Parameters: 2207 + mat - the matrix 2208 . nrow - number of rows 2209 . irow - the row local indices 2210 . ncol - number of columns 2211 - icol - the column local indices 2212 2213 Output Parameter: 2214 . y - a logically two-dimensional array of values 2215 2216 Level: advanced 2217 2218 Notes: 2219 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2220 2221 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, 2222 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2223 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2224 with `MatSetLocalToGlobalMapping()`. 2225 2226 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2227 `MatSetValuesLocal()`, `MatGetValues()` 2228 @*/ 2229 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2230 { 2231 PetscFunctionBeginHot; 2232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2233 PetscValidType(mat, 1); 2234 MatCheckPreallocated(mat, 1); 2235 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2236 PetscAssertPointer(irow, 3); 2237 PetscAssertPointer(icol, 5); 2238 if (PetscDefined(USE_DEBUG)) { 2239 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2240 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2241 } 2242 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2243 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2244 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2245 else { 2246 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2247 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2248 irowm = buf; 2249 icolm = buf + nrow; 2250 } else { 2251 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2252 irowm = bufr; 2253 icolm = bufc; 2254 } 2255 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2256 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2257 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2258 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2259 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2260 PetscCall(PetscFree2(bufr, bufc)); 2261 } 2262 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2263 PetscFunctionReturn(PETSC_SUCCESS); 2264 } 2265 2266 /*@ 2267 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2268 the same size. Currently, this can only be called once and creates the given matrix. 2269 2270 Not Collective 2271 2272 Input Parameters: 2273 + mat - the matrix 2274 . nb - the number of blocks 2275 . bs - the number of rows (and columns) in each block 2276 . rows - a concatenation of the rows for each block 2277 - v - a concatenation of logically two-dimensional arrays of values 2278 2279 Level: advanced 2280 2281 Notes: 2282 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2283 2284 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2285 2286 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2287 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2288 @*/ 2289 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2290 { 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2293 PetscValidType(mat, 1); 2294 PetscAssertPointer(rows, 4); 2295 PetscAssertPointer(v, 5); 2296 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2297 2298 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2299 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2300 else { 2301 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2302 } 2303 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2304 PetscFunctionReturn(PETSC_SUCCESS); 2305 } 2306 2307 /*@ 2308 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2309 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2310 using a local (per-processor) numbering. 2311 2312 Not Collective 2313 2314 Input Parameters: 2315 + x - the matrix 2316 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2317 - cmapping - column mapping 2318 2319 Level: intermediate 2320 2321 Note: 2322 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2323 2324 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2325 @*/ 2326 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2327 { 2328 PetscFunctionBegin; 2329 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2330 PetscValidType(x, 1); 2331 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2332 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2333 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2334 else { 2335 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2336 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2337 } 2338 PetscFunctionReturn(PETSC_SUCCESS); 2339 } 2340 2341 /*@ 2342 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2343 2344 Not Collective 2345 2346 Input Parameter: 2347 . A - the matrix 2348 2349 Output Parameters: 2350 + rmapping - row mapping 2351 - cmapping - column mapping 2352 2353 Level: advanced 2354 2355 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2356 @*/ 2357 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2358 { 2359 PetscFunctionBegin; 2360 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2361 PetscValidType(A, 1); 2362 if (rmapping) { 2363 PetscAssertPointer(rmapping, 2); 2364 *rmapping = A->rmap->mapping; 2365 } 2366 if (cmapping) { 2367 PetscAssertPointer(cmapping, 3); 2368 *cmapping = A->cmap->mapping; 2369 } 2370 PetscFunctionReturn(PETSC_SUCCESS); 2371 } 2372 2373 /*@ 2374 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2375 2376 Logically Collective 2377 2378 Input Parameters: 2379 + A - the matrix 2380 . rmap - row layout 2381 - cmap - column layout 2382 2383 Level: advanced 2384 2385 Note: 2386 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2387 2388 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2389 @*/ 2390 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2391 { 2392 PetscFunctionBegin; 2393 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2394 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2395 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2396 PetscFunctionReturn(PETSC_SUCCESS); 2397 } 2398 2399 /*@ 2400 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2401 2402 Not Collective 2403 2404 Input Parameter: 2405 . A - the matrix 2406 2407 Output Parameters: 2408 + rmap - row layout 2409 - cmap - column layout 2410 2411 Level: advanced 2412 2413 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2414 @*/ 2415 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2419 PetscValidType(A, 1); 2420 if (rmap) { 2421 PetscAssertPointer(rmap, 2); 2422 *rmap = A->rmap; 2423 } 2424 if (cmap) { 2425 PetscAssertPointer(cmap, 3); 2426 *cmap = A->cmap; 2427 } 2428 PetscFunctionReturn(PETSC_SUCCESS); 2429 } 2430 2431 /*@ 2432 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2433 using a local numbering of the rows and columns. 2434 2435 Not Collective 2436 2437 Input Parameters: 2438 + mat - the matrix 2439 . nrow - number of rows 2440 . irow - the row local indices 2441 . ncol - number of columns 2442 . icol - the column local indices 2443 . y - a logically two-dimensional array of values 2444 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2445 2446 Level: intermediate 2447 2448 Notes: 2449 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2450 2451 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2452 options cannot be mixed without intervening calls to the assembly 2453 routines. 2454 2455 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2456 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2457 2458 Fortran Notes: 2459 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2460 .vb 2461 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2462 .ve 2463 2464 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2465 2466 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2467 `MatGetValuesLocal()` 2468 @*/ 2469 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2470 { 2471 PetscFunctionBeginHot; 2472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2473 PetscValidType(mat, 1); 2474 MatCheckPreallocated(mat, 1); 2475 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2476 PetscAssertPointer(irow, 3); 2477 PetscAssertPointer(icol, 5); 2478 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2479 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2480 if (PetscDefined(USE_DEBUG)) { 2481 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2482 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2483 } 2484 2485 if (mat->assembled) { 2486 mat->was_assembled = PETSC_TRUE; 2487 mat->assembled = PETSC_FALSE; 2488 } 2489 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2490 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2491 else { 2492 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2493 const PetscInt *irowm, *icolm; 2494 2495 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2496 bufr = buf; 2497 bufc = buf + nrow; 2498 irowm = bufr; 2499 icolm = bufc; 2500 } else { 2501 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2502 irowm = bufr; 2503 icolm = bufc; 2504 } 2505 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2506 else irowm = irow; 2507 if (mat->cmap->mapping) { 2508 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2509 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2510 } else icolm = irowm; 2511 } else icolm = icol; 2512 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2513 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2514 } 2515 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2516 PetscFunctionReturn(PETSC_SUCCESS); 2517 } 2518 2519 /*@ 2520 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2521 using a local ordering of the nodes a block at a time. 2522 2523 Not Collective 2524 2525 Input Parameters: 2526 + mat - the matrix 2527 . nrow - number of rows 2528 . irow - the row local indices 2529 . ncol - number of columns 2530 . icol - the column local indices 2531 . y - a logically two-dimensional array of values 2532 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2533 2534 Level: intermediate 2535 2536 Notes: 2537 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2538 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2539 2540 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2541 options cannot be mixed without intervening calls to the assembly 2542 routines. 2543 2544 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2545 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2546 2547 Fortran Notes: 2548 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2549 .vb 2550 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2551 .ve 2552 2553 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2554 2555 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2556 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2557 @*/ 2558 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2559 { 2560 PetscFunctionBeginHot; 2561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2562 PetscValidType(mat, 1); 2563 MatCheckPreallocated(mat, 1); 2564 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2565 PetscAssertPointer(irow, 3); 2566 PetscAssertPointer(icol, 5); 2567 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2568 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2569 if (PetscDefined(USE_DEBUG)) { 2570 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2571 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); 2572 } 2573 2574 if (mat->assembled) { 2575 mat->was_assembled = PETSC_TRUE; 2576 mat->assembled = PETSC_FALSE; 2577 } 2578 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2579 PetscInt irbs, rbs; 2580 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2581 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2582 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2583 } 2584 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2585 PetscInt icbs, cbs; 2586 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2587 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2588 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2589 } 2590 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2591 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2592 else { 2593 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2594 const PetscInt *irowm, *icolm; 2595 2596 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2597 bufr = buf; 2598 bufc = buf + nrow; 2599 irowm = bufr; 2600 icolm = bufc; 2601 } else { 2602 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2603 irowm = bufr; 2604 icolm = bufc; 2605 } 2606 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2607 else irowm = irow; 2608 if (mat->cmap->mapping) { 2609 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2610 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2611 } else icolm = irowm; 2612 } else icolm = icol; 2613 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2614 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2615 } 2616 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2617 PetscFunctionReturn(PETSC_SUCCESS); 2618 } 2619 2620 /*@ 2621 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2622 2623 Collective 2624 2625 Input Parameters: 2626 + mat - the matrix 2627 - x - the vector to be multiplied 2628 2629 Output Parameter: 2630 . y - the result 2631 2632 Level: developer 2633 2634 Note: 2635 The vectors `x` and `y` cannot be the same. I.e., one cannot 2636 call `MatMultDiagonalBlock`(A,y,y). 2637 2638 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2639 @*/ 2640 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2641 { 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2644 PetscValidType(mat, 1); 2645 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2646 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2647 2648 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2649 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2650 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2651 MatCheckPreallocated(mat, 1); 2652 2653 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2654 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2655 PetscFunctionReturn(PETSC_SUCCESS); 2656 } 2657 2658 /*@ 2659 MatMult - Computes the matrix-vector product, $y = Ax$. 2660 2661 Neighbor-wise Collective 2662 2663 Input Parameters: 2664 + mat - the matrix 2665 - x - the vector to be multiplied 2666 2667 Output Parameter: 2668 . y - the result 2669 2670 Level: beginner 2671 2672 Note: 2673 The vectors `x` and `y` cannot be the same. I.e., one cannot 2674 call `MatMult`(A,y,y). 2675 2676 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2677 @*/ 2678 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2679 { 2680 PetscFunctionBegin; 2681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2682 PetscValidType(mat, 1); 2683 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2684 VecCheckAssembled(x); 2685 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2686 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2687 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2688 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2689 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); 2690 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); 2691 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); 2692 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); 2693 PetscCall(VecSetErrorIfLocked(y, 3)); 2694 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2695 MatCheckPreallocated(mat, 1); 2696 2697 PetscCall(VecLockReadPush(x)); 2698 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2699 PetscUseTypeMethod(mat, mult, x, y); 2700 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2701 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2702 PetscCall(VecLockReadPop(x)); 2703 PetscFunctionReturn(PETSC_SUCCESS); 2704 } 2705 2706 /*@ 2707 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2708 2709 Neighbor-wise Collective 2710 2711 Input Parameters: 2712 + mat - the matrix 2713 - x - the vector to be multiplied 2714 2715 Output Parameter: 2716 . y - the result 2717 2718 Level: beginner 2719 2720 Notes: 2721 The vectors `x` and `y` cannot be the same. I.e., one cannot 2722 call `MatMultTranspose`(A,y,y). 2723 2724 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2725 use `MatMultHermitianTranspose()` 2726 2727 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2728 @*/ 2729 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2730 { 2731 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2732 2733 PetscFunctionBegin; 2734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2735 PetscValidType(mat, 1); 2736 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2737 VecCheckAssembled(x); 2738 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2739 2740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2742 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2743 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); 2744 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); 2745 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); 2746 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); 2747 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2748 MatCheckPreallocated(mat, 1); 2749 2750 if (!mat->ops->multtranspose) { 2751 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2752 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); 2753 } else op = mat->ops->multtranspose; 2754 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2755 PetscCall(VecLockReadPush(x)); 2756 PetscCall((*op)(mat, x, y)); 2757 PetscCall(VecLockReadPop(x)); 2758 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2759 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2760 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2761 PetscFunctionReturn(PETSC_SUCCESS); 2762 } 2763 2764 /*@ 2765 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2766 2767 Neighbor-wise Collective 2768 2769 Input Parameters: 2770 + mat - the matrix 2771 - x - the vector to be multiplied 2772 2773 Output Parameter: 2774 . y - the result 2775 2776 Level: beginner 2777 2778 Notes: 2779 The vectors `x` and `y` cannot be the same. I.e., one cannot 2780 call `MatMultHermitianTranspose`(A,y,y). 2781 2782 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2783 2784 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2785 2786 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2787 @*/ 2788 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2789 { 2790 PetscFunctionBegin; 2791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2792 PetscValidType(mat, 1); 2793 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2794 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2795 2796 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2797 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2798 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2799 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); 2800 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); 2801 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); 2802 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); 2803 MatCheckPreallocated(mat, 1); 2804 2805 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2806 #if defined(PETSC_USE_COMPLEX) 2807 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2808 PetscCall(VecLockReadPush(x)); 2809 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2810 else PetscUseTypeMethod(mat, mult, x, y); 2811 PetscCall(VecLockReadPop(x)); 2812 } else { 2813 Vec w; 2814 PetscCall(VecDuplicate(x, &w)); 2815 PetscCall(VecCopy(x, w)); 2816 PetscCall(VecConjugate(w)); 2817 PetscCall(MatMultTranspose(mat, w, y)); 2818 PetscCall(VecDestroy(&w)); 2819 PetscCall(VecConjugate(y)); 2820 } 2821 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2822 #else 2823 PetscCall(MatMultTranspose(mat, x, y)); 2824 #endif 2825 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2826 PetscFunctionReturn(PETSC_SUCCESS); 2827 } 2828 2829 /*@ 2830 MatMultAdd - Computes $v3 = v2 + A * v1$. 2831 2832 Neighbor-wise Collective 2833 2834 Input Parameters: 2835 + mat - the matrix 2836 . v1 - the vector to be multiplied by `mat` 2837 - v2 - the vector to be added to the result 2838 2839 Output Parameter: 2840 . v3 - the result 2841 2842 Level: beginner 2843 2844 Note: 2845 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2846 call `MatMultAdd`(A,v1,v2,v1). 2847 2848 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2849 @*/ 2850 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2851 { 2852 PetscFunctionBegin; 2853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2854 PetscValidType(mat, 1); 2855 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2856 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2857 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2858 2859 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2860 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2861 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); 2862 /* 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); 2863 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); */ 2864 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); 2865 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); 2866 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2867 MatCheckPreallocated(mat, 1); 2868 2869 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2870 PetscCall(VecLockReadPush(v1)); 2871 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2872 PetscCall(VecLockReadPop(v1)); 2873 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2874 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2875 PetscFunctionReturn(PETSC_SUCCESS); 2876 } 2877 2878 /*@ 2879 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2880 2881 Neighbor-wise Collective 2882 2883 Input Parameters: 2884 + mat - the matrix 2885 . v1 - the vector to be multiplied by the transpose of the matrix 2886 - v2 - the vector to be added to the result 2887 2888 Output Parameter: 2889 . v3 - the result 2890 2891 Level: beginner 2892 2893 Note: 2894 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2895 call `MatMultTransposeAdd`(A,v1,v2,v1). 2896 2897 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2898 @*/ 2899 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2900 { 2901 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2902 2903 PetscFunctionBegin; 2904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2905 PetscValidType(mat, 1); 2906 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2907 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2908 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2909 2910 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2911 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2912 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); 2913 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); 2914 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); 2915 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2916 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2917 MatCheckPreallocated(mat, 1); 2918 2919 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2920 PetscCall(VecLockReadPush(v1)); 2921 PetscCall((*op)(mat, v1, v2, v3)); 2922 PetscCall(VecLockReadPop(v1)); 2923 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2924 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2925 PetscFunctionReturn(PETSC_SUCCESS); 2926 } 2927 2928 /*@ 2929 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2930 2931 Neighbor-wise Collective 2932 2933 Input Parameters: 2934 + mat - the matrix 2935 . v1 - the vector to be multiplied by the Hermitian transpose 2936 - v2 - the vector to be added to the result 2937 2938 Output Parameter: 2939 . v3 - the result 2940 2941 Level: beginner 2942 2943 Note: 2944 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2945 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2946 2947 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2948 @*/ 2949 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2950 { 2951 PetscFunctionBegin; 2952 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2953 PetscValidType(mat, 1); 2954 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2955 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2956 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2957 2958 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2959 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2960 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2961 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); 2962 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); 2963 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); 2964 MatCheckPreallocated(mat, 1); 2965 2966 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2967 PetscCall(VecLockReadPush(v1)); 2968 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2969 else { 2970 Vec w, z; 2971 PetscCall(VecDuplicate(v1, &w)); 2972 PetscCall(VecCopy(v1, w)); 2973 PetscCall(VecConjugate(w)); 2974 PetscCall(VecDuplicate(v3, &z)); 2975 PetscCall(MatMultTranspose(mat, w, z)); 2976 PetscCall(VecDestroy(&w)); 2977 PetscCall(VecConjugate(z)); 2978 if (v2 != v3) { 2979 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2980 } else { 2981 PetscCall(VecAXPY(v3, 1.0, z)); 2982 } 2983 PetscCall(VecDestroy(&z)); 2984 } 2985 PetscCall(VecLockReadPop(v1)); 2986 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2987 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2988 PetscFunctionReturn(PETSC_SUCCESS); 2989 } 2990 2991 /*@ 2992 MatGetFactorType - gets the type of factorization a matrix is 2993 2994 Not Collective 2995 2996 Input Parameter: 2997 . mat - the matrix 2998 2999 Output Parameter: 3000 . 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` 3001 3002 Level: intermediate 3003 3004 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3005 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3006 @*/ 3007 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3008 { 3009 PetscFunctionBegin; 3010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3011 PetscValidType(mat, 1); 3012 PetscAssertPointer(t, 2); 3013 *t = mat->factortype; 3014 PetscFunctionReturn(PETSC_SUCCESS); 3015 } 3016 3017 /*@ 3018 MatSetFactorType - sets the type of factorization a matrix is 3019 3020 Logically Collective 3021 3022 Input Parameters: 3023 + mat - the matrix 3024 - 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` 3025 3026 Level: intermediate 3027 3028 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3029 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3030 @*/ 3031 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3032 { 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 PetscValidType(mat, 1); 3036 mat->factortype = t; 3037 PetscFunctionReturn(PETSC_SUCCESS); 3038 } 3039 3040 /*@ 3041 MatGetInfo - Returns information about matrix storage (number of 3042 nonzeros, memory, etc.). 3043 3044 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3045 3046 Input Parameters: 3047 + mat - the matrix 3048 - 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) 3049 3050 Output Parameter: 3051 . info - matrix information context 3052 3053 Options Database Key: 3054 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3055 3056 Level: intermediate 3057 3058 Notes: 3059 The `MatInfo` context contains a variety of matrix data, including 3060 number of nonzeros allocated and used, number of mallocs during 3061 matrix assembly, etc. Additional information for factored matrices 3062 is provided (such as the fill ratio, number of mallocs during 3063 factorization, etc.). 3064 3065 Example: 3066 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3067 data within the `MatInfo` context. For example, 3068 .vb 3069 MatInfo info; 3070 Mat A; 3071 double mal, nz_a, nz_u; 3072 3073 MatGetInfo(A, MAT_LOCAL, &info); 3074 mal = info.mallocs; 3075 nz_a = info.nz_allocated; 3076 .ve 3077 3078 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3079 @*/ 3080 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3081 { 3082 PetscFunctionBegin; 3083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3084 PetscValidType(mat, 1); 3085 PetscAssertPointer(info, 3); 3086 MatCheckPreallocated(mat, 1); 3087 PetscUseTypeMethod(mat, getinfo, flag, info); 3088 PetscFunctionReturn(PETSC_SUCCESS); 3089 } 3090 3091 /* 3092 This is used by external packages where it is not easy to get the info from the actual 3093 matrix factorization. 3094 */ 3095 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3096 { 3097 PetscFunctionBegin; 3098 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3099 PetscFunctionReturn(PETSC_SUCCESS); 3100 } 3101 3102 /*@ 3103 MatLUFactor - Performs in-place LU factorization of matrix. 3104 3105 Collective 3106 3107 Input Parameters: 3108 + mat - the matrix 3109 . row - row permutation 3110 . col - column permutation 3111 - info - options for factorization, includes 3112 .vb 3113 fill - expected fill as ratio of original fill. 3114 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3115 Run with the option -info to determine an optimal value to use 3116 .ve 3117 3118 Level: developer 3119 3120 Notes: 3121 Most users should employ the `KSP` interface for linear solvers 3122 instead of working directly with matrix algebra routines such as this. 3123 See, e.g., `KSPCreate()`. 3124 3125 This changes the state of the matrix to a factored matrix; it cannot be used 3126 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3127 3128 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3129 when not using `KSP`. 3130 3131 Fortran Note: 3132 A valid (non-null) `info` argument must be provided 3133 3134 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3135 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3136 @*/ 3137 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3138 { 3139 MatFactorInfo tinfo; 3140 3141 PetscFunctionBegin; 3142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3143 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3144 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3145 if (info) PetscAssertPointer(info, 4); 3146 PetscValidType(mat, 1); 3147 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3148 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3149 MatCheckPreallocated(mat, 1); 3150 if (!info) { 3151 PetscCall(MatFactorInfoInitialize(&tinfo)); 3152 info = &tinfo; 3153 } 3154 3155 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3156 PetscUseTypeMethod(mat, lufactor, row, col, info); 3157 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3158 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3159 PetscFunctionReturn(PETSC_SUCCESS); 3160 } 3161 3162 /*@ 3163 MatILUFactor - Performs in-place ILU factorization of matrix. 3164 3165 Collective 3166 3167 Input Parameters: 3168 + mat - the matrix 3169 . row - row permutation 3170 . col - column permutation 3171 - info - structure containing 3172 .vb 3173 levels - number of levels of fill. 3174 expected fill - as ratio of original fill. 3175 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3176 missing diagonal entries) 3177 .ve 3178 3179 Level: developer 3180 3181 Notes: 3182 Most users should employ the `KSP` interface for linear solvers 3183 instead of working directly with matrix algebra routines such as this. 3184 See, e.g., `KSPCreate()`. 3185 3186 Probably really in-place only when level of fill is zero, otherwise allocates 3187 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3188 when not using `KSP`. 3189 3190 Fortran Note: 3191 A valid (non-null) `info` argument must be provided 3192 3193 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3194 @*/ 3195 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3196 { 3197 PetscFunctionBegin; 3198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3199 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3200 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3201 PetscAssertPointer(info, 4); 3202 PetscValidType(mat, 1); 3203 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3205 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3206 MatCheckPreallocated(mat, 1); 3207 3208 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3209 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3210 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3211 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3212 PetscFunctionReturn(PETSC_SUCCESS); 3213 } 3214 3215 /*@ 3216 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3217 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3218 3219 Collective 3220 3221 Input Parameters: 3222 + fact - the factor matrix obtained with `MatGetFactor()` 3223 . mat - the matrix 3224 . row - the row permutation 3225 . col - the column permutation 3226 - info - options for factorization, includes 3227 .vb 3228 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3229 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3230 .ve 3231 3232 Level: developer 3233 3234 Notes: 3235 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3236 3237 Most users should employ the simplified `KSP` interface for linear solvers 3238 instead of working directly with matrix algebra routines such as this. 3239 See, e.g., `KSPCreate()`. 3240 3241 Fortran Note: 3242 A valid (non-null) `info` argument must be provided 3243 3244 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3245 @*/ 3246 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3247 { 3248 MatFactorInfo tinfo; 3249 3250 PetscFunctionBegin; 3251 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3252 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3253 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3254 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3255 if (info) PetscAssertPointer(info, 5); 3256 PetscValidType(fact, 1); 3257 PetscValidType(mat, 2); 3258 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3259 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3260 MatCheckPreallocated(mat, 2); 3261 if (!info) { 3262 PetscCall(MatFactorInfoInitialize(&tinfo)); 3263 info = &tinfo; 3264 } 3265 3266 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3267 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3268 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3269 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3270 PetscFunctionReturn(PETSC_SUCCESS); 3271 } 3272 3273 /*@ 3274 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3275 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3276 3277 Collective 3278 3279 Input Parameters: 3280 + fact - the factor matrix obtained with `MatGetFactor()` 3281 . mat - the matrix 3282 - info - options for factorization 3283 3284 Level: developer 3285 3286 Notes: 3287 See `MatLUFactor()` for in-place factorization. See 3288 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3289 3290 Most users should employ the `KSP` interface for linear solvers 3291 instead of working directly with matrix algebra routines such as this. 3292 See, e.g., `KSPCreate()`. 3293 3294 Fortran Note: 3295 A valid (non-null) `info` argument must be provided 3296 3297 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3298 @*/ 3299 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3300 { 3301 MatFactorInfo tinfo; 3302 3303 PetscFunctionBegin; 3304 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3306 PetscValidType(fact, 1); 3307 PetscValidType(mat, 2); 3308 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3309 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, 3310 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3311 3312 MatCheckPreallocated(mat, 2); 3313 if (!info) { 3314 PetscCall(MatFactorInfoInitialize(&tinfo)); 3315 info = &tinfo; 3316 } 3317 3318 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3319 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3320 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3321 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3322 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3323 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3324 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3325 PetscFunctionReturn(PETSC_SUCCESS); 3326 } 3327 3328 /*@ 3329 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3330 symmetric matrix. 3331 3332 Collective 3333 3334 Input Parameters: 3335 + mat - the matrix 3336 . perm - row and column permutations 3337 - info - expected fill as ratio of original fill 3338 3339 Level: developer 3340 3341 Notes: 3342 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3343 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3344 3345 Most users should employ the `KSP` interface for linear solvers 3346 instead of working directly with matrix algebra routines such as this. 3347 See, e.g., `KSPCreate()`. 3348 3349 Fortran Note: 3350 A valid (non-null) `info` argument must be provided 3351 3352 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3353 `MatGetOrdering()` 3354 @*/ 3355 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3356 { 3357 MatFactorInfo tinfo; 3358 3359 PetscFunctionBegin; 3360 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3361 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3362 if (info) PetscAssertPointer(info, 3); 3363 PetscValidType(mat, 1); 3364 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3365 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3366 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3367 MatCheckPreallocated(mat, 1); 3368 if (!info) { 3369 PetscCall(MatFactorInfoInitialize(&tinfo)); 3370 info = &tinfo; 3371 } 3372 3373 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3374 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3375 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3376 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3377 PetscFunctionReturn(PETSC_SUCCESS); 3378 } 3379 3380 /*@ 3381 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3382 of a symmetric matrix. 3383 3384 Collective 3385 3386 Input Parameters: 3387 + fact - the factor matrix obtained with `MatGetFactor()` 3388 . mat - the matrix 3389 . perm - row and column permutations 3390 - info - options for factorization, includes 3391 .vb 3392 fill - expected fill as ratio of original fill. 3393 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3394 Run with the option -info to determine an optimal value to use 3395 .ve 3396 3397 Level: developer 3398 3399 Notes: 3400 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3401 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3402 3403 Most users should employ the `KSP` interface for linear solvers 3404 instead of working directly with matrix algebra routines such as this. 3405 See, e.g., `KSPCreate()`. 3406 3407 Fortran Note: 3408 A valid (non-null) `info` argument must be provided 3409 3410 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3411 `MatGetOrdering()` 3412 @*/ 3413 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3414 { 3415 MatFactorInfo tinfo; 3416 3417 PetscFunctionBegin; 3418 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3420 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3421 if (info) PetscAssertPointer(info, 4); 3422 PetscValidType(fact, 1); 3423 PetscValidType(mat, 2); 3424 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3425 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3426 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3427 MatCheckPreallocated(mat, 2); 3428 if (!info) { 3429 PetscCall(MatFactorInfoInitialize(&tinfo)); 3430 info = &tinfo; 3431 } 3432 3433 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3434 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3435 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3436 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3437 PetscFunctionReturn(PETSC_SUCCESS); 3438 } 3439 3440 /*@ 3441 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3442 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3443 `MatCholeskyFactorSymbolic()`. 3444 3445 Collective 3446 3447 Input Parameters: 3448 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3449 . mat - the initial matrix that is to be factored 3450 - info - options for factorization 3451 3452 Level: developer 3453 3454 Note: 3455 Most users should employ the `KSP` interface for linear solvers 3456 instead of working directly with matrix algebra routines such as this. 3457 See, e.g., `KSPCreate()`. 3458 3459 Fortran Note: 3460 A valid (non-null) `info` argument must be provided 3461 3462 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3463 @*/ 3464 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3465 { 3466 MatFactorInfo tinfo; 3467 3468 PetscFunctionBegin; 3469 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3471 PetscValidType(fact, 1); 3472 PetscValidType(mat, 2); 3473 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3474 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, 3475 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3476 MatCheckPreallocated(mat, 2); 3477 if (!info) { 3478 PetscCall(MatFactorInfoInitialize(&tinfo)); 3479 info = &tinfo; 3480 } 3481 3482 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3483 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3484 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3485 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3486 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3487 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3488 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3489 PetscFunctionReturn(PETSC_SUCCESS); 3490 } 3491 3492 /*@ 3493 MatQRFactor - Performs in-place QR factorization of matrix. 3494 3495 Collective 3496 3497 Input Parameters: 3498 + mat - the matrix 3499 . col - column permutation 3500 - info - options for factorization, includes 3501 .vb 3502 fill - expected fill as ratio of original fill. 3503 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3504 Run with the option -info to determine an optimal value to use 3505 .ve 3506 3507 Level: developer 3508 3509 Notes: 3510 Most users should employ the `KSP` interface for linear solvers 3511 instead of working directly with matrix algebra routines such as this. 3512 See, e.g., `KSPCreate()`. 3513 3514 This changes the state of the matrix to a factored matrix; it cannot be used 3515 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3516 3517 Fortran Note: 3518 A valid (non-null) `info` argument must be provided 3519 3520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3521 `MatSetUnfactored()` 3522 @*/ 3523 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3524 { 3525 PetscFunctionBegin; 3526 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3527 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3528 if (info) PetscAssertPointer(info, 3); 3529 PetscValidType(mat, 1); 3530 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3531 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3532 MatCheckPreallocated(mat, 1); 3533 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3534 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3535 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3536 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3537 PetscFunctionReturn(PETSC_SUCCESS); 3538 } 3539 3540 /*@ 3541 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3542 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3543 3544 Collective 3545 3546 Input Parameters: 3547 + fact - the factor matrix obtained with `MatGetFactor()` 3548 . mat - the matrix 3549 . col - column permutation 3550 - info - options for factorization, includes 3551 .vb 3552 fill - expected fill as ratio of original fill. 3553 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3554 Run with the option -info to determine an optimal value to use 3555 .ve 3556 3557 Level: developer 3558 3559 Note: 3560 Most users should employ the `KSP` interface for linear solvers 3561 instead of working directly with matrix algebra routines such as this. 3562 See, e.g., `KSPCreate()`. 3563 3564 Fortran Note: 3565 A valid (non-null) `info` argument must be provided 3566 3567 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3568 @*/ 3569 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3570 { 3571 MatFactorInfo tinfo; 3572 3573 PetscFunctionBegin; 3574 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3575 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3576 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3577 if (info) PetscAssertPointer(info, 4); 3578 PetscValidType(fact, 1); 3579 PetscValidType(mat, 2); 3580 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3581 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3582 MatCheckPreallocated(mat, 2); 3583 if (!info) { 3584 PetscCall(MatFactorInfoInitialize(&tinfo)); 3585 info = &tinfo; 3586 } 3587 3588 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3589 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3590 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3591 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3592 PetscFunctionReturn(PETSC_SUCCESS); 3593 } 3594 3595 /*@ 3596 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3597 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3598 3599 Collective 3600 3601 Input Parameters: 3602 + fact - the factor matrix obtained with `MatGetFactor()` 3603 . mat - the matrix 3604 - info - options for factorization 3605 3606 Level: developer 3607 3608 Notes: 3609 See `MatQRFactor()` for in-place factorization. 3610 3611 Most users should employ the `KSP` interface for linear solvers 3612 instead of working directly with matrix algebra routines such as this. 3613 See, e.g., `KSPCreate()`. 3614 3615 Fortran Note: 3616 A valid (non-null) `info` argument must be provided 3617 3618 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3619 @*/ 3620 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3621 { 3622 MatFactorInfo tinfo; 3623 3624 PetscFunctionBegin; 3625 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3627 PetscValidType(fact, 1); 3628 PetscValidType(mat, 2); 3629 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3630 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, 3631 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3632 3633 MatCheckPreallocated(mat, 2); 3634 if (!info) { 3635 PetscCall(MatFactorInfoInitialize(&tinfo)); 3636 info = &tinfo; 3637 } 3638 3639 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3640 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3641 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3642 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3643 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3644 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3645 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3646 PetscFunctionReturn(PETSC_SUCCESS); 3647 } 3648 3649 /*@ 3650 MatSolve - Solves $A x = b$, given a factored matrix. 3651 3652 Neighbor-wise Collective 3653 3654 Input Parameters: 3655 + mat - the factored matrix 3656 - b - the right-hand-side vector 3657 3658 Output Parameter: 3659 . x - the result vector 3660 3661 Level: developer 3662 3663 Notes: 3664 The vectors `b` and `x` cannot be the same. I.e., one cannot 3665 call `MatSolve`(A,x,x). 3666 3667 Most users should employ the `KSP` interface for linear solvers 3668 instead of working directly with matrix algebra routines such as this. 3669 See, e.g., `KSPCreate()`. 3670 3671 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3672 @*/ 3673 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3674 { 3675 PetscFunctionBegin; 3676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3677 PetscValidType(mat, 1); 3678 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3679 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3680 PetscCheckSameComm(mat, 1, b, 2); 3681 PetscCheckSameComm(mat, 1, x, 3); 3682 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3683 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); 3684 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); 3685 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); 3686 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3687 MatCheckPreallocated(mat, 1); 3688 3689 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3690 PetscCall(VecFlag(x, mat->factorerrortype)); 3691 if (mat->factorerrortype) { 3692 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3693 } else PetscUseTypeMethod(mat, solve, b, x); 3694 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3695 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3696 PetscFunctionReturn(PETSC_SUCCESS); 3697 } 3698 3699 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3700 { 3701 Vec b, x; 3702 PetscInt N, i; 3703 PetscErrorCode (*f)(Mat, Vec, Vec); 3704 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3705 3706 PetscFunctionBegin; 3707 if (A->factorerrortype) { 3708 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3709 PetscCall(MatSetInf(X)); 3710 PetscFunctionReturn(PETSC_SUCCESS); 3711 } 3712 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3713 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3714 PetscCall(MatBoundToCPU(A, &Abound)); 3715 if (!Abound) { 3716 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3717 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3718 } 3719 #if PetscDefined(HAVE_CUDA) 3720 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3721 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3722 #elif PetscDefined(HAVE_HIP) 3723 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3724 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3725 #endif 3726 PetscCall(MatGetSize(B, NULL, &N)); 3727 for (i = 0; i < N; i++) { 3728 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3729 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3730 PetscCall((*f)(A, b, x)); 3731 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3732 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3733 } 3734 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3735 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3736 PetscFunctionReturn(PETSC_SUCCESS); 3737 } 3738 3739 /*@ 3740 MatMatSolve - Solves $A X = B$, given a factored matrix. 3741 3742 Neighbor-wise Collective 3743 3744 Input Parameters: 3745 + A - the factored matrix 3746 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3747 3748 Output Parameter: 3749 . X - the result matrix (dense matrix) 3750 3751 Level: developer 3752 3753 Note: 3754 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3755 otherwise, `B` and `X` cannot be the same. 3756 3757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3758 @*/ 3759 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3760 { 3761 PetscFunctionBegin; 3762 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3763 PetscValidType(A, 1); 3764 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3765 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3766 PetscCheckSameComm(A, 1, B, 2); 3767 PetscCheckSameComm(A, 1, X, 3); 3768 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); 3769 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); 3770 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"); 3771 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3772 MatCheckPreallocated(A, 1); 3773 3774 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3775 if (!A->ops->matsolve) { 3776 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3777 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3778 } else PetscUseTypeMethod(A, matsolve, B, X); 3779 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3780 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3781 PetscFunctionReturn(PETSC_SUCCESS); 3782 } 3783 3784 /*@ 3785 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3786 3787 Neighbor-wise Collective 3788 3789 Input Parameters: 3790 + A - the factored matrix 3791 - B - the right-hand-side matrix (`MATDENSE` matrix) 3792 3793 Output Parameter: 3794 . X - the result matrix (dense matrix) 3795 3796 Level: developer 3797 3798 Note: 3799 The matrices `B` and `X` cannot be the same. I.e., one cannot 3800 call `MatMatSolveTranspose`(A,X,X). 3801 3802 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3803 @*/ 3804 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3805 { 3806 PetscFunctionBegin; 3807 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3808 PetscValidType(A, 1); 3809 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3810 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3811 PetscCheckSameComm(A, 1, B, 2); 3812 PetscCheckSameComm(A, 1, X, 3); 3813 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3814 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); 3815 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); 3816 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); 3817 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"); 3818 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3819 MatCheckPreallocated(A, 1); 3820 3821 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3822 if (!A->ops->matsolvetranspose) { 3823 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3824 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3825 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3826 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3827 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3828 PetscFunctionReturn(PETSC_SUCCESS); 3829 } 3830 3831 /*@ 3832 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3833 3834 Neighbor-wise Collective 3835 3836 Input Parameters: 3837 + A - the factored matrix 3838 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3839 3840 Output Parameter: 3841 . X - the result matrix (dense matrix) 3842 3843 Level: developer 3844 3845 Note: 3846 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 3847 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3848 3849 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3850 @*/ 3851 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3852 { 3853 PetscFunctionBegin; 3854 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3855 PetscValidType(A, 1); 3856 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3857 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3858 PetscCheckSameComm(A, 1, Bt, 2); 3859 PetscCheckSameComm(A, 1, X, 3); 3860 3861 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3862 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); 3863 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); 3864 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"); 3865 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3866 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3867 MatCheckPreallocated(A, 1); 3868 3869 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3870 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3871 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3872 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3873 PetscFunctionReturn(PETSC_SUCCESS); 3874 } 3875 3876 /*@ 3877 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3878 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3879 3880 Neighbor-wise Collective 3881 3882 Input Parameters: 3883 + mat - the factored matrix 3884 - b - the right-hand-side vector 3885 3886 Output Parameter: 3887 . x - the result vector 3888 3889 Level: developer 3890 3891 Notes: 3892 `MatSolve()` should be used for most applications, as it performs 3893 a forward solve followed by a backward solve. 3894 3895 The vectors `b` and `x` cannot be the same, i.e., one cannot 3896 call `MatForwardSolve`(A,x,x). 3897 3898 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3899 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3900 `MatForwardSolve()` solves $U^T*D y = b$, and 3901 `MatBackwardSolve()` solves $U x = y$. 3902 Thus they do not provide a symmetric preconditioner. 3903 3904 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3905 @*/ 3906 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3907 { 3908 PetscFunctionBegin; 3909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3910 PetscValidType(mat, 1); 3911 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3912 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3913 PetscCheckSameComm(mat, 1, b, 2); 3914 PetscCheckSameComm(mat, 1, x, 3); 3915 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3916 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); 3917 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); 3918 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); 3919 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3920 MatCheckPreallocated(mat, 1); 3921 3922 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3923 PetscUseTypeMethod(mat, forwardsolve, b, x); 3924 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3925 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3926 PetscFunctionReturn(PETSC_SUCCESS); 3927 } 3928 3929 /*@ 3930 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3931 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3932 3933 Neighbor-wise Collective 3934 3935 Input Parameters: 3936 + mat - the factored matrix 3937 - b - the right-hand-side vector 3938 3939 Output Parameter: 3940 . x - the result vector 3941 3942 Level: developer 3943 3944 Notes: 3945 `MatSolve()` should be used for most applications, as it performs 3946 a forward solve followed by a backward solve. 3947 3948 The vectors `b` and `x` cannot be the same. I.e., one cannot 3949 call `MatBackwardSolve`(A,x,x). 3950 3951 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3952 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3953 `MatForwardSolve()` solves $U^T*D y = b$, and 3954 `MatBackwardSolve()` solves $U x = y$. 3955 Thus they do not provide a symmetric preconditioner. 3956 3957 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3958 @*/ 3959 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3960 { 3961 PetscFunctionBegin; 3962 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3963 PetscValidType(mat, 1); 3964 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3965 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3966 PetscCheckSameComm(mat, 1, b, 2); 3967 PetscCheckSameComm(mat, 1, x, 3); 3968 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3969 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); 3970 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); 3971 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); 3972 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3973 MatCheckPreallocated(mat, 1); 3974 3975 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3976 PetscUseTypeMethod(mat, backwardsolve, b, x); 3977 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3978 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3979 PetscFunctionReturn(PETSC_SUCCESS); 3980 } 3981 3982 /*@ 3983 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3984 3985 Neighbor-wise Collective 3986 3987 Input Parameters: 3988 + mat - the factored matrix 3989 . b - the right-hand-side vector 3990 - y - the vector to be added to 3991 3992 Output Parameter: 3993 . x - the result vector 3994 3995 Level: developer 3996 3997 Note: 3998 The vectors `b` and `x` cannot be the same. I.e., one cannot 3999 call `MatSolveAdd`(A,x,y,x). 4000 4001 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4002 @*/ 4003 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4004 { 4005 PetscScalar one = 1.0; 4006 Vec tmp; 4007 4008 PetscFunctionBegin; 4009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4010 PetscValidType(mat, 1); 4011 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4012 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4013 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4014 PetscCheckSameComm(mat, 1, b, 2); 4015 PetscCheckSameComm(mat, 1, y, 3); 4016 PetscCheckSameComm(mat, 1, x, 4); 4017 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4018 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); 4019 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); 4020 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); 4021 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); 4022 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); 4023 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4024 MatCheckPreallocated(mat, 1); 4025 4026 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4027 PetscCall(VecFlag(x, mat->factorerrortype)); 4028 if (mat->factorerrortype) { 4029 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4030 } else if (mat->ops->solveadd) { 4031 PetscUseTypeMethod(mat, solveadd, b, y, x); 4032 } else { 4033 /* do the solve then the add manually */ 4034 if (x != y) { 4035 PetscCall(MatSolve(mat, b, x)); 4036 PetscCall(VecAXPY(x, one, y)); 4037 } else { 4038 PetscCall(VecDuplicate(x, &tmp)); 4039 PetscCall(VecCopy(x, tmp)); 4040 PetscCall(MatSolve(mat, b, x)); 4041 PetscCall(VecAXPY(x, one, tmp)); 4042 PetscCall(VecDestroy(&tmp)); 4043 } 4044 } 4045 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4046 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4047 PetscFunctionReturn(PETSC_SUCCESS); 4048 } 4049 4050 /*@ 4051 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4052 4053 Neighbor-wise Collective 4054 4055 Input Parameters: 4056 + mat - the factored matrix 4057 - b - the right-hand-side vector 4058 4059 Output Parameter: 4060 . x - the result vector 4061 4062 Level: developer 4063 4064 Notes: 4065 The vectors `b` and `x` cannot be the same. I.e., one cannot 4066 call `MatSolveTranspose`(A,x,x). 4067 4068 Most users should employ the `KSP` interface for linear solvers 4069 instead of working directly with matrix algebra routines such as this. 4070 See, e.g., `KSPCreate()`. 4071 4072 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4073 @*/ 4074 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4075 { 4076 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4077 4078 PetscFunctionBegin; 4079 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4080 PetscValidType(mat, 1); 4081 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4082 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4083 PetscCheckSameComm(mat, 1, b, 2); 4084 PetscCheckSameComm(mat, 1, x, 3); 4085 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4086 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); 4087 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); 4088 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4089 MatCheckPreallocated(mat, 1); 4090 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4091 PetscCall(VecFlag(x, mat->factorerrortype)); 4092 if (mat->factorerrortype) { 4093 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4094 } else { 4095 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4096 PetscCall((*f)(mat, b, x)); 4097 } 4098 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4099 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4100 PetscFunctionReturn(PETSC_SUCCESS); 4101 } 4102 4103 /*@ 4104 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4105 factored matrix. 4106 4107 Neighbor-wise Collective 4108 4109 Input Parameters: 4110 + mat - the factored matrix 4111 . b - the right-hand-side vector 4112 - y - the vector to be added to 4113 4114 Output Parameter: 4115 . x - the result vector 4116 4117 Level: developer 4118 4119 Note: 4120 The vectors `b` and `x` cannot be the same. I.e., one cannot 4121 call `MatSolveTransposeAdd`(A,x,y,x). 4122 4123 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4124 @*/ 4125 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4126 { 4127 PetscScalar one = 1.0; 4128 Vec tmp; 4129 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4130 4131 PetscFunctionBegin; 4132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4133 PetscValidType(mat, 1); 4134 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4135 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4136 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4137 PetscCheckSameComm(mat, 1, b, 2); 4138 PetscCheckSameComm(mat, 1, y, 3); 4139 PetscCheckSameComm(mat, 1, x, 4); 4140 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4141 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); 4142 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); 4143 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); 4144 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); 4145 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4146 MatCheckPreallocated(mat, 1); 4147 4148 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4149 PetscCall(VecFlag(x, mat->factorerrortype)); 4150 if (mat->factorerrortype) { 4151 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4152 } else if (f) { 4153 PetscCall((*f)(mat, b, y, x)); 4154 } else { 4155 /* do the solve then the add manually */ 4156 if (x != y) { 4157 PetscCall(MatSolveTranspose(mat, b, x)); 4158 PetscCall(VecAXPY(x, one, y)); 4159 } else { 4160 PetscCall(VecDuplicate(x, &tmp)); 4161 PetscCall(VecCopy(x, tmp)); 4162 PetscCall(MatSolveTranspose(mat, b, x)); 4163 PetscCall(VecAXPY(x, one, tmp)); 4164 PetscCall(VecDestroy(&tmp)); 4165 } 4166 } 4167 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4168 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4169 PetscFunctionReturn(PETSC_SUCCESS); 4170 } 4171 4172 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4173 /*@ 4174 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4175 4176 Neighbor-wise Collective 4177 4178 Input Parameters: 4179 + mat - the matrix 4180 . b - the right-hand side 4181 . omega - the relaxation factor 4182 . flag - flag indicating the type of SOR (see below) 4183 . shift - diagonal shift 4184 . its - the number of iterations 4185 - lits - the number of local iterations 4186 4187 Output Parameter: 4188 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4189 4190 SOR Flags: 4191 + `SOR_FORWARD_SWEEP` - forward SOR 4192 . `SOR_BACKWARD_SWEEP` - backward SOR 4193 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4194 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4195 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4196 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4197 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4198 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4199 upper/lower triangular part of matrix to 4200 vector (with omega) 4201 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4202 4203 Level: developer 4204 4205 Notes: 4206 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4207 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4208 on each processor. 4209 4210 Application programmers will not generally use `MatSOR()` directly, 4211 but instead will employ the `KSP`/`PC` interface. 4212 4213 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4214 4215 Most users should employ the `KSP` interface for linear solvers 4216 instead of working directly with matrix algebra routines such as this. 4217 See, e.g., `KSPCreate()`. 4218 4219 Vectors `x` and `b` CANNOT be the same 4220 4221 The flags are implemented as bitwise inclusive or operations. 4222 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4223 to specify a zero initial guess for SSOR. 4224 4225 Developer Note: 4226 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4227 4228 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4229 @*/ 4230 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4231 { 4232 PetscFunctionBegin; 4233 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4234 PetscValidType(mat, 1); 4235 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4236 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4237 PetscCheckSameComm(mat, 1, b, 2); 4238 PetscCheckSameComm(mat, 1, x, 8); 4239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4240 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4241 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); 4242 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); 4243 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); 4244 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4245 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4246 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4247 4248 MatCheckPreallocated(mat, 1); 4249 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4250 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4251 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4252 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4253 PetscFunctionReturn(PETSC_SUCCESS); 4254 } 4255 4256 /* 4257 Default matrix copy routine. 4258 */ 4259 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4260 { 4261 PetscInt i, rstart = 0, rend = 0, nz; 4262 const PetscInt *cwork; 4263 const PetscScalar *vwork; 4264 4265 PetscFunctionBegin; 4266 if (B->assembled) PetscCall(MatZeroEntries(B)); 4267 if (str == SAME_NONZERO_PATTERN) { 4268 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4269 for (i = rstart; i < rend; i++) { 4270 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4271 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4272 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4273 } 4274 } else { 4275 PetscCall(MatAYPX(B, 0.0, A, str)); 4276 } 4277 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4278 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4279 PetscFunctionReturn(PETSC_SUCCESS); 4280 } 4281 4282 /*@ 4283 MatCopy - Copies a matrix to another matrix. 4284 4285 Collective 4286 4287 Input Parameters: 4288 + A - the matrix 4289 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4290 4291 Output Parameter: 4292 . B - where the copy is put 4293 4294 Level: intermediate 4295 4296 Notes: 4297 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4298 4299 `MatCopy()` copies the matrix entries of a matrix to another existing 4300 matrix (after first zeroing the second matrix). A related routine is 4301 `MatConvert()`, which first creates a new matrix and then copies the data. 4302 4303 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4304 @*/ 4305 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4306 { 4307 PetscInt i; 4308 4309 PetscFunctionBegin; 4310 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4311 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4312 PetscValidType(A, 1); 4313 PetscValidType(B, 2); 4314 PetscCheckSameComm(A, 1, B, 2); 4315 MatCheckPreallocated(B, 2); 4316 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4317 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4318 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, 4319 A->cmap->N, B->cmap->N); 4320 MatCheckPreallocated(A, 1); 4321 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4322 4323 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4324 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4325 else PetscCall(MatCopy_Basic(A, B, str)); 4326 4327 B->stencil.dim = A->stencil.dim; 4328 B->stencil.noc = A->stencil.noc; 4329 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4330 B->stencil.dims[i] = A->stencil.dims[i]; 4331 B->stencil.starts[i] = A->stencil.starts[i]; 4332 } 4333 4334 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4335 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4336 PetscFunctionReturn(PETSC_SUCCESS); 4337 } 4338 4339 /*@ 4340 MatConvert - Converts a matrix to another matrix, either of the same 4341 or different type. 4342 4343 Collective 4344 4345 Input Parameters: 4346 + mat - the matrix 4347 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4348 same type as the original matrix. 4349 - reuse - denotes if the destination matrix is to be created or reused. 4350 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 4351 `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). 4352 4353 Output Parameter: 4354 . M - pointer to place new matrix 4355 4356 Level: intermediate 4357 4358 Notes: 4359 `MatConvert()` first creates a new matrix and then copies the data from 4360 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4361 entries of one matrix to another already existing matrix context. 4362 4363 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4364 the MPI communicator of the generated matrix is always the same as the communicator 4365 of the input matrix. 4366 4367 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4368 @*/ 4369 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4370 { 4371 PetscBool sametype, issame, flg; 4372 PetscBool3 issymmetric, ishermitian; 4373 char convname[256], mtype[256]; 4374 Mat B; 4375 4376 PetscFunctionBegin; 4377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4378 PetscValidType(mat, 1); 4379 PetscAssertPointer(M, 4); 4380 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4381 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4382 MatCheckPreallocated(mat, 1); 4383 4384 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4385 if (flg) newtype = mtype; 4386 4387 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4388 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4389 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4390 if (reuse == MAT_REUSE_MATRIX) { 4391 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4392 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4393 } 4394 4395 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4396 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4397 PetscFunctionReturn(PETSC_SUCCESS); 4398 } 4399 4400 /* Cache Mat options because some converters use MatHeaderReplace */ 4401 issymmetric = mat->symmetric; 4402 ishermitian = mat->hermitian; 4403 4404 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4405 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4406 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4407 } else { 4408 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4409 const char *prefix[3] = {"seq", "mpi", ""}; 4410 PetscInt i; 4411 /* 4412 Order of precedence: 4413 0) See if newtype is a superclass of the current matrix. 4414 1) See if a specialized converter is known to the current matrix. 4415 2) See if a specialized converter is known to the desired matrix class. 4416 3) See if a good general converter is registered for the desired class 4417 (as of 6/27/03 only MATMPIADJ falls into this category). 4418 4) See if a good general converter is known for the current matrix. 4419 5) Use a really basic converter. 4420 */ 4421 4422 /* 0) See if newtype is a superclass of the current matrix. 4423 i.e mat is mpiaij and newtype is aij */ 4424 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4425 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4426 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4427 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4428 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4429 if (flg) { 4430 if (reuse == MAT_INPLACE_MATRIX) { 4431 PetscCall(PetscInfo(mat, "Early return\n")); 4432 PetscFunctionReturn(PETSC_SUCCESS); 4433 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4434 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4435 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4436 PetscFunctionReturn(PETSC_SUCCESS); 4437 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4438 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4439 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4440 PetscFunctionReturn(PETSC_SUCCESS); 4441 } 4442 } 4443 } 4444 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4445 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4446 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4447 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4448 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4449 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4450 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4451 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4452 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4453 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4454 if (conv) goto foundconv; 4455 } 4456 4457 /* 2) See if a specialized converter is known to the desired matrix class. */ 4458 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4459 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4460 PetscCall(MatSetType(B, newtype)); 4461 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4462 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4463 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4464 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4465 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4466 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4467 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4468 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4469 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4470 if (conv) { 4471 PetscCall(MatDestroy(&B)); 4472 goto foundconv; 4473 } 4474 } 4475 4476 /* 3) See if a good general converter is registered for the desired class */ 4477 conv = B->ops->convertfrom; 4478 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4479 PetscCall(MatDestroy(&B)); 4480 if (conv) goto foundconv; 4481 4482 /* 4) See if a good general converter is known for the current matrix */ 4483 if (mat->ops->convert) conv = mat->ops->convert; 4484 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4485 if (conv) goto foundconv; 4486 4487 /* 5) Use a really basic converter. */ 4488 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4489 conv = MatConvert_Basic; 4490 4491 foundconv: 4492 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4493 PetscCall((*conv)(mat, newtype, reuse, M)); 4494 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4495 /* the block sizes must be same if the mappings are copied over */ 4496 (*M)->rmap->bs = mat->rmap->bs; 4497 (*M)->cmap->bs = mat->cmap->bs; 4498 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4499 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4500 (*M)->rmap->mapping = mat->rmap->mapping; 4501 (*M)->cmap->mapping = mat->cmap->mapping; 4502 } 4503 (*M)->stencil.dim = mat->stencil.dim; 4504 (*M)->stencil.noc = mat->stencil.noc; 4505 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4506 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4507 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4508 } 4509 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4510 } 4511 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4512 4513 /* Copy Mat options */ 4514 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4515 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4516 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4517 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4518 PetscFunctionReturn(PETSC_SUCCESS); 4519 } 4520 4521 /*@ 4522 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4523 4524 Not Collective 4525 4526 Input Parameter: 4527 . mat - the matrix, must be a factored matrix 4528 4529 Output Parameter: 4530 . type - the string name of the package (do not free this string) 4531 4532 Level: intermediate 4533 4534 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4535 @*/ 4536 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4537 { 4538 PetscErrorCode (*conv)(Mat, MatSolverType *); 4539 4540 PetscFunctionBegin; 4541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4542 PetscValidType(mat, 1); 4543 PetscAssertPointer(type, 2); 4544 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4545 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4546 if (conv) PetscCall((*conv)(mat, type)); 4547 else *type = MATSOLVERPETSC; 4548 PetscFunctionReturn(PETSC_SUCCESS); 4549 } 4550 4551 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4552 struct _MatSolverTypeForSpecifcType { 4553 MatType mtype; 4554 /* no entry for MAT_FACTOR_NONE */ 4555 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4556 MatSolverTypeForSpecifcType next; 4557 }; 4558 4559 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4560 struct _MatSolverTypeHolder { 4561 char *name; 4562 MatSolverTypeForSpecifcType handlers; 4563 MatSolverTypeHolder next; 4564 }; 4565 4566 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4567 4568 /*@C 4569 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4570 4571 Logically Collective, No Fortran Support 4572 4573 Input Parameters: 4574 + package - name of the package, for example `petsc` or `superlu` 4575 . mtype - the matrix type that works with this package 4576 . ftype - the type of factorization supported by the package 4577 - createfactor - routine that will create the factored matrix ready to be used 4578 4579 Level: developer 4580 4581 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4582 `MatGetFactor()` 4583 @*/ 4584 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4585 { 4586 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4587 PetscBool flg; 4588 MatSolverTypeForSpecifcType inext, iprev = NULL; 4589 4590 PetscFunctionBegin; 4591 PetscCall(MatInitializePackage()); 4592 if (!next) { 4593 PetscCall(PetscNew(&MatSolverTypeHolders)); 4594 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4595 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4596 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4597 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4598 PetscFunctionReturn(PETSC_SUCCESS); 4599 } 4600 while (next) { 4601 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4602 if (flg) { 4603 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4604 inext = next->handlers; 4605 while (inext) { 4606 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4607 if (flg) { 4608 inext->createfactor[(int)ftype - 1] = createfactor; 4609 PetscFunctionReturn(PETSC_SUCCESS); 4610 } 4611 iprev = inext; 4612 inext = inext->next; 4613 } 4614 PetscCall(PetscNew(&iprev->next)); 4615 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4616 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4617 PetscFunctionReturn(PETSC_SUCCESS); 4618 } 4619 prev = next; 4620 next = next->next; 4621 } 4622 PetscCall(PetscNew(&prev->next)); 4623 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4624 PetscCall(PetscNew(&prev->next->handlers)); 4625 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4626 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4627 PetscFunctionReturn(PETSC_SUCCESS); 4628 } 4629 4630 /*@C 4631 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4632 4633 Input Parameters: 4634 + 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 4635 . ftype - the type of factorization supported by the type 4636 - mtype - the matrix type that works with this type 4637 4638 Output Parameters: 4639 + foundtype - `PETSC_TRUE` if the type was registered 4640 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4641 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4642 4643 Calling sequence of `createfactor`: 4644 + A - the matrix providing the factor matrix 4645 . ftype - the `MatFactorType` of the factor requested 4646 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4647 4648 Level: developer 4649 4650 Note: 4651 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4652 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4653 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4654 4655 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4656 `MatInitializePackage()` 4657 @*/ 4658 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4659 { 4660 MatSolverTypeHolder next = MatSolverTypeHolders; 4661 PetscBool flg; 4662 MatSolverTypeForSpecifcType inext; 4663 4664 PetscFunctionBegin; 4665 if (foundtype) *foundtype = PETSC_FALSE; 4666 if (foundmtype) *foundmtype = PETSC_FALSE; 4667 if (createfactor) *createfactor = NULL; 4668 4669 if (type) { 4670 while (next) { 4671 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4672 if (flg) { 4673 if (foundtype) *foundtype = PETSC_TRUE; 4674 inext = next->handlers; 4675 while (inext) { 4676 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4677 if (flg) { 4678 if (foundmtype) *foundmtype = PETSC_TRUE; 4679 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4680 PetscFunctionReturn(PETSC_SUCCESS); 4681 } 4682 inext = inext->next; 4683 } 4684 } 4685 next = next->next; 4686 } 4687 } else { 4688 while (next) { 4689 inext = next->handlers; 4690 while (inext) { 4691 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4692 if (flg && inext->createfactor[(int)ftype - 1]) { 4693 if (foundtype) *foundtype = PETSC_TRUE; 4694 if (foundmtype) *foundmtype = PETSC_TRUE; 4695 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4696 PetscFunctionReturn(PETSC_SUCCESS); 4697 } 4698 inext = inext->next; 4699 } 4700 next = next->next; 4701 } 4702 /* try with base classes inext->mtype */ 4703 next = MatSolverTypeHolders; 4704 while (next) { 4705 inext = next->handlers; 4706 while (inext) { 4707 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4708 if (flg && inext->createfactor[(int)ftype - 1]) { 4709 if (foundtype) *foundtype = PETSC_TRUE; 4710 if (foundmtype) *foundmtype = PETSC_TRUE; 4711 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4712 PetscFunctionReturn(PETSC_SUCCESS); 4713 } 4714 inext = inext->next; 4715 } 4716 next = next->next; 4717 } 4718 } 4719 PetscFunctionReturn(PETSC_SUCCESS); 4720 } 4721 4722 PetscErrorCode MatSolverTypeDestroy(void) 4723 { 4724 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4725 MatSolverTypeForSpecifcType inext, iprev; 4726 4727 PetscFunctionBegin; 4728 while (next) { 4729 PetscCall(PetscFree(next->name)); 4730 inext = next->handlers; 4731 while (inext) { 4732 PetscCall(PetscFree(inext->mtype)); 4733 iprev = inext; 4734 inext = inext->next; 4735 PetscCall(PetscFree(iprev)); 4736 } 4737 prev = next; 4738 next = next->next; 4739 PetscCall(PetscFree(prev)); 4740 } 4741 MatSolverTypeHolders = NULL; 4742 PetscFunctionReturn(PETSC_SUCCESS); 4743 } 4744 4745 /*@ 4746 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4747 4748 Logically Collective 4749 4750 Input Parameter: 4751 . mat - the matrix 4752 4753 Output Parameter: 4754 . flg - `PETSC_TRUE` if uses the ordering 4755 4756 Level: developer 4757 4758 Note: 4759 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4760 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4761 4762 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4763 @*/ 4764 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4765 { 4766 PetscFunctionBegin; 4767 *flg = mat->canuseordering; 4768 PetscFunctionReturn(PETSC_SUCCESS); 4769 } 4770 4771 /*@ 4772 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4773 4774 Logically Collective 4775 4776 Input Parameters: 4777 + mat - the matrix obtained with `MatGetFactor()` 4778 - ftype - the factorization type to be used 4779 4780 Output Parameter: 4781 . otype - the preferred ordering type 4782 4783 Level: developer 4784 4785 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4786 @*/ 4787 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4788 { 4789 PetscFunctionBegin; 4790 *otype = mat->preferredordering[ftype]; 4791 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4792 PetscFunctionReturn(PETSC_SUCCESS); 4793 } 4794 4795 /*@ 4796 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4797 4798 Collective 4799 4800 Input Parameters: 4801 + mat - the matrix 4802 . 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 4803 the other criteria is returned 4804 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4805 4806 Output Parameter: 4807 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4808 4809 Options Database Keys: 4810 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4811 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4812 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4813 4814 Level: intermediate 4815 4816 Notes: 4817 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4818 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4819 4820 Users usually access the factorization solvers via `KSP` 4821 4822 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4823 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 4824 4825 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4826 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4827 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4828 4829 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4830 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4831 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4832 4833 Developer Note: 4834 This should actually be called `MatCreateFactor()` since it creates a new factor object 4835 4836 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4837 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4838 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4839 @*/ 4840 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4841 { 4842 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4843 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4844 4845 PetscFunctionBegin; 4846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4847 PetscValidType(mat, 1); 4848 4849 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4850 MatCheckPreallocated(mat, 1); 4851 4852 PetscCall(MatIsShell(mat, &shell)); 4853 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4854 if (hasop) { 4855 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4856 PetscFunctionReturn(PETSC_SUCCESS); 4857 } 4858 4859 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4860 if (!foundtype) { 4861 if (type) { 4862 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], 4863 ((PetscObject)mat)->type_name, type); 4864 } else { 4865 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); 4866 } 4867 } 4868 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4869 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); 4870 4871 PetscCall((*conv)(mat, ftype, f)); 4872 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4873 PetscFunctionReturn(PETSC_SUCCESS); 4874 } 4875 4876 /*@ 4877 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4878 4879 Not Collective 4880 4881 Input Parameters: 4882 + mat - the matrix 4883 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4884 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4885 4886 Output Parameter: 4887 . flg - PETSC_TRUE if the factorization is available 4888 4889 Level: intermediate 4890 4891 Notes: 4892 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4893 such as pastix, superlu, mumps etc. 4894 4895 PETSc must have been ./configure to use the external solver, using the option --download-package 4896 4897 Developer Note: 4898 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4899 4900 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4901 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4902 @*/ 4903 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4904 { 4905 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4906 4907 PetscFunctionBegin; 4908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4909 PetscAssertPointer(flg, 4); 4910 4911 *flg = PETSC_FALSE; 4912 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4913 4914 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4915 MatCheckPreallocated(mat, 1); 4916 4917 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4918 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4919 PetscFunctionReturn(PETSC_SUCCESS); 4920 } 4921 4922 /*@ 4923 MatDuplicate - Duplicates a matrix including the non-zero structure. 4924 4925 Collective 4926 4927 Input Parameters: 4928 + mat - the matrix 4929 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4930 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4931 4932 Output Parameter: 4933 . M - pointer to place new matrix 4934 4935 Level: intermediate 4936 4937 Notes: 4938 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4939 4940 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4941 4942 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. 4943 4944 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4945 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4946 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4947 4948 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4949 @*/ 4950 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4951 { 4952 Mat B; 4953 VecType vtype; 4954 PetscInt i; 4955 PetscObject dm, container_h, container_d; 4956 void (*viewf)(void); 4957 4958 PetscFunctionBegin; 4959 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4960 PetscValidType(mat, 1); 4961 PetscAssertPointer(M, 3); 4962 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4963 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4964 MatCheckPreallocated(mat, 1); 4965 4966 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4967 PetscUseTypeMethod(mat, duplicate, op, M); 4968 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4969 B = *M; 4970 4971 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4972 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4973 PetscCall(MatGetVecType(mat, &vtype)); 4974 PetscCall(MatSetVecType(B, vtype)); 4975 4976 B->stencil.dim = mat->stencil.dim; 4977 B->stencil.noc = mat->stencil.noc; 4978 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4979 B->stencil.dims[i] = mat->stencil.dims[i]; 4980 B->stencil.starts[i] = mat->stencil.starts[i]; 4981 } 4982 4983 B->nooffproczerorows = mat->nooffproczerorows; 4984 B->nooffprocentries = mat->nooffprocentries; 4985 4986 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4987 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4988 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4989 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4990 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4991 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4992 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4993 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4994 PetscFunctionReturn(PETSC_SUCCESS); 4995 } 4996 4997 /*@ 4998 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4999 5000 Logically Collective 5001 5002 Input Parameter: 5003 . mat - the matrix 5004 5005 Output Parameter: 5006 . v - the diagonal of the matrix 5007 5008 Level: intermediate 5009 5010 Note: 5011 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5012 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5013 is larger than `ndiag`, the values of the remaining entries are unspecified. 5014 5015 Currently only correct in parallel for square matrices. 5016 5017 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5018 @*/ 5019 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5020 { 5021 PetscFunctionBegin; 5022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5023 PetscValidType(mat, 1); 5024 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5025 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5026 MatCheckPreallocated(mat, 1); 5027 if (PetscDefined(USE_DEBUG)) { 5028 PetscInt nv, row, col, ndiag; 5029 5030 PetscCall(VecGetLocalSize(v, &nv)); 5031 PetscCall(MatGetLocalSize(mat, &row, &col)); 5032 ndiag = PetscMin(row, col); 5033 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); 5034 } 5035 5036 PetscUseTypeMethod(mat, getdiagonal, v); 5037 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5038 PetscFunctionReturn(PETSC_SUCCESS); 5039 } 5040 5041 /*@ 5042 MatGetRowMin - Gets the minimum value (of the real part) of each 5043 row of the matrix 5044 5045 Logically Collective 5046 5047 Input Parameter: 5048 . mat - the matrix 5049 5050 Output Parameters: 5051 + v - the vector for storing the maximums 5052 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5053 5054 Level: intermediate 5055 5056 Note: 5057 The result of this call are the same as if one converted the matrix to dense format 5058 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5059 5060 This code is only implemented for a couple of matrix formats. 5061 5062 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5063 `MatGetRowMax()` 5064 @*/ 5065 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5066 { 5067 PetscFunctionBegin; 5068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5069 PetscValidType(mat, 1); 5070 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5071 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5072 5073 if (!mat->cmap->N) { 5074 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5075 if (idx) { 5076 PetscInt i, m = mat->rmap->n; 5077 for (i = 0; i < m; i++) idx[i] = -1; 5078 } 5079 } else { 5080 MatCheckPreallocated(mat, 1); 5081 } 5082 PetscUseTypeMethod(mat, getrowmin, v, idx); 5083 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5084 PetscFunctionReturn(PETSC_SUCCESS); 5085 } 5086 5087 /*@ 5088 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5089 row of the matrix 5090 5091 Logically Collective 5092 5093 Input Parameter: 5094 . mat - the matrix 5095 5096 Output Parameters: 5097 + v - the vector for storing the minimums 5098 - idx - the indices of the column found for each row (or `NULL` if not needed) 5099 5100 Level: intermediate 5101 5102 Notes: 5103 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5104 row is 0 (the first column). 5105 5106 This code is only implemented for a couple of matrix formats. 5107 5108 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5109 @*/ 5110 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5111 { 5112 PetscFunctionBegin; 5113 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5114 PetscValidType(mat, 1); 5115 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5116 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5117 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5118 5119 if (!mat->cmap->N) { 5120 PetscCall(VecSet(v, 0.0)); 5121 if (idx) { 5122 PetscInt i, m = mat->rmap->n; 5123 for (i = 0; i < m; i++) idx[i] = -1; 5124 } 5125 } else { 5126 MatCheckPreallocated(mat, 1); 5127 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5128 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5129 } 5130 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5131 PetscFunctionReturn(PETSC_SUCCESS); 5132 } 5133 5134 /*@ 5135 MatGetRowMax - Gets the maximum value (of the real part) of each 5136 row of the matrix 5137 5138 Logically Collective 5139 5140 Input Parameter: 5141 . mat - the matrix 5142 5143 Output Parameters: 5144 + v - the vector for storing the maximums 5145 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5146 5147 Level: intermediate 5148 5149 Notes: 5150 The result of this call are the same as if one converted the matrix to dense format 5151 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5152 5153 This code is only implemented for a couple of matrix formats. 5154 5155 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5156 @*/ 5157 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5158 { 5159 PetscFunctionBegin; 5160 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5161 PetscValidType(mat, 1); 5162 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5163 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5164 5165 if (!mat->cmap->N) { 5166 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5167 if (idx) { 5168 PetscInt i, m = mat->rmap->n; 5169 for (i = 0; i < m; i++) idx[i] = -1; 5170 } 5171 } else { 5172 MatCheckPreallocated(mat, 1); 5173 PetscUseTypeMethod(mat, getrowmax, v, idx); 5174 } 5175 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5176 PetscFunctionReturn(PETSC_SUCCESS); 5177 } 5178 5179 /*@ 5180 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5181 row of the matrix 5182 5183 Logically Collective 5184 5185 Input Parameter: 5186 . mat - the matrix 5187 5188 Output Parameters: 5189 + v - the vector for storing the maximums 5190 - idx - the indices of the column found for each row (or `NULL` if not needed) 5191 5192 Level: intermediate 5193 5194 Notes: 5195 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5196 row is 0 (the first column). 5197 5198 This code is only implemented for a couple of matrix formats. 5199 5200 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5201 @*/ 5202 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5203 { 5204 PetscFunctionBegin; 5205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5206 PetscValidType(mat, 1); 5207 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5208 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5209 5210 if (!mat->cmap->N) { 5211 PetscCall(VecSet(v, 0.0)); 5212 if (idx) { 5213 PetscInt i, m = mat->rmap->n; 5214 for (i = 0; i < m; i++) idx[i] = -1; 5215 } 5216 } else { 5217 MatCheckPreallocated(mat, 1); 5218 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5219 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5220 } 5221 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5222 PetscFunctionReturn(PETSC_SUCCESS); 5223 } 5224 5225 /*@ 5226 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5227 5228 Logically Collective 5229 5230 Input Parameter: 5231 . mat - the matrix 5232 5233 Output Parameter: 5234 . v - the vector for storing the sum 5235 5236 Level: intermediate 5237 5238 This code is only implemented for a couple of matrix formats. 5239 5240 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5241 @*/ 5242 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5243 { 5244 PetscFunctionBegin; 5245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5246 PetscValidType(mat, 1); 5247 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5248 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5249 5250 if (!mat->cmap->N) { 5251 PetscCall(VecSet(v, 0.0)); 5252 } else { 5253 MatCheckPreallocated(mat, 1); 5254 PetscUseTypeMethod(mat, getrowsumabs, v); 5255 } 5256 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5257 PetscFunctionReturn(PETSC_SUCCESS); 5258 } 5259 5260 /*@ 5261 MatGetRowSum - Gets the sum of each row of the matrix 5262 5263 Logically or Neighborhood Collective 5264 5265 Input Parameter: 5266 . mat - the matrix 5267 5268 Output Parameter: 5269 . v - the vector for storing the sum of rows 5270 5271 Level: intermediate 5272 5273 Note: 5274 This code is slow since it is not currently specialized for different formats 5275 5276 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5277 @*/ 5278 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5279 { 5280 Vec ones; 5281 5282 PetscFunctionBegin; 5283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5284 PetscValidType(mat, 1); 5285 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5286 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5287 MatCheckPreallocated(mat, 1); 5288 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5289 PetscCall(VecSet(ones, 1.)); 5290 PetscCall(MatMult(mat, ones, v)); 5291 PetscCall(VecDestroy(&ones)); 5292 PetscFunctionReturn(PETSC_SUCCESS); 5293 } 5294 5295 /*@ 5296 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5297 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5298 5299 Collective 5300 5301 Input Parameter: 5302 . mat - the matrix to provide the transpose 5303 5304 Output Parameter: 5305 . 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 5306 5307 Level: advanced 5308 5309 Note: 5310 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 5311 routine allows bypassing that call. 5312 5313 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5314 @*/ 5315 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5316 { 5317 MatParentState *rb = NULL; 5318 5319 PetscFunctionBegin; 5320 PetscCall(PetscNew(&rb)); 5321 rb->id = ((PetscObject)mat)->id; 5322 rb->state = 0; 5323 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5324 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5325 PetscFunctionReturn(PETSC_SUCCESS); 5326 } 5327 5328 /*@ 5329 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5330 5331 Collective 5332 5333 Input Parameters: 5334 + mat - the matrix to transpose 5335 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5336 5337 Output Parameter: 5338 . B - the transpose of the matrix 5339 5340 Level: intermediate 5341 5342 Notes: 5343 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5344 5345 `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 5346 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5347 5348 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. 5349 5350 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5351 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5352 5353 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5354 5355 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5356 5357 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5358 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5359 @*/ 5360 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5361 { 5362 PetscContainer rB = NULL; 5363 MatParentState *rb = NULL; 5364 5365 PetscFunctionBegin; 5366 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5367 PetscValidType(mat, 1); 5368 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5369 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5370 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5371 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5372 MatCheckPreallocated(mat, 1); 5373 if (reuse == MAT_REUSE_MATRIX) { 5374 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5375 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5376 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5377 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5378 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5379 } 5380 5381 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5382 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5383 PetscUseTypeMethod(mat, transpose, reuse, B); 5384 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5385 } 5386 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5387 5388 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5389 if (reuse != MAT_INPLACE_MATRIX) { 5390 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5391 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5392 rb->state = ((PetscObject)mat)->state; 5393 rb->nonzerostate = mat->nonzerostate; 5394 } 5395 PetscFunctionReturn(PETSC_SUCCESS); 5396 } 5397 5398 /*@ 5399 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5400 5401 Collective 5402 5403 Input Parameter: 5404 . A - the matrix to transpose 5405 5406 Output Parameter: 5407 . 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 5408 numerical portion. 5409 5410 Level: intermediate 5411 5412 Note: 5413 This is not supported for many matrix types, use `MatTranspose()` in those cases 5414 5415 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5416 @*/ 5417 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5418 { 5419 PetscFunctionBegin; 5420 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5421 PetscValidType(A, 1); 5422 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5423 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5424 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5425 PetscUseTypeMethod(A, transposesymbolic, B); 5426 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5427 5428 PetscCall(MatTransposeSetPrecursor(A, *B)); 5429 PetscFunctionReturn(PETSC_SUCCESS); 5430 } 5431 5432 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5433 { 5434 PetscContainer rB; 5435 MatParentState *rb; 5436 5437 PetscFunctionBegin; 5438 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5439 PetscValidType(A, 1); 5440 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5441 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5442 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5443 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5444 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5445 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5446 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5447 PetscFunctionReturn(PETSC_SUCCESS); 5448 } 5449 5450 /*@ 5451 MatIsTranspose - Test whether a matrix is another one's transpose, 5452 or its own, in which case it tests symmetry. 5453 5454 Collective 5455 5456 Input Parameters: 5457 + A - the matrix to test 5458 . B - the matrix to test against, this can equal the first parameter 5459 - tol - tolerance, differences between entries smaller than this are counted as zero 5460 5461 Output Parameter: 5462 . flg - the result 5463 5464 Level: intermediate 5465 5466 Notes: 5467 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5468 test involves parallel copies of the block off-diagonal parts of the matrix. 5469 5470 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5471 @*/ 5472 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5473 { 5474 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5475 5476 PetscFunctionBegin; 5477 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5478 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5479 PetscAssertPointer(flg, 4); 5480 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5481 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5482 *flg = PETSC_FALSE; 5483 if (f && g) { 5484 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5485 PetscCall((*f)(A, B, tol, flg)); 5486 } else { 5487 MatType mattype; 5488 5489 PetscCall(MatGetType(f ? B : A, &mattype)); 5490 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5491 } 5492 PetscFunctionReturn(PETSC_SUCCESS); 5493 } 5494 5495 /*@ 5496 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5497 5498 Collective 5499 5500 Input Parameters: 5501 + mat - the matrix to transpose and complex conjugate 5502 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5503 5504 Output Parameter: 5505 . B - the Hermitian transpose 5506 5507 Level: intermediate 5508 5509 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5510 @*/ 5511 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5512 { 5513 PetscFunctionBegin; 5514 PetscCall(MatTranspose(mat, reuse, B)); 5515 #if defined(PETSC_USE_COMPLEX) 5516 PetscCall(MatConjugate(*B)); 5517 #endif 5518 PetscFunctionReturn(PETSC_SUCCESS); 5519 } 5520 5521 /*@ 5522 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5523 5524 Collective 5525 5526 Input Parameters: 5527 + A - the matrix to test 5528 . B - the matrix to test against, this can equal the first parameter 5529 - tol - tolerance, differences between entries smaller than this are counted as zero 5530 5531 Output Parameter: 5532 . flg - the result 5533 5534 Level: intermediate 5535 5536 Notes: 5537 Only available for `MATAIJ` matrices. 5538 5539 The sequential algorithm 5540 has a running time of the order of the number of nonzeros; the parallel 5541 test involves parallel copies of the block off-diagonal parts of the matrix. 5542 5543 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5544 @*/ 5545 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5546 { 5547 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5548 5549 PetscFunctionBegin; 5550 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5551 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5552 PetscAssertPointer(flg, 4); 5553 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5554 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5555 if (f && g) { 5556 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5557 PetscCall((*f)(A, B, tol, flg)); 5558 } 5559 PetscFunctionReturn(PETSC_SUCCESS); 5560 } 5561 5562 /*@ 5563 MatPermute - Creates a new matrix with rows and columns permuted from the 5564 original. 5565 5566 Collective 5567 5568 Input Parameters: 5569 + mat - the matrix to permute 5570 . row - row permutation, each processor supplies only the permutation for its rows 5571 - col - column permutation, each processor supplies only the permutation for its columns 5572 5573 Output Parameter: 5574 . B - the permuted matrix 5575 5576 Level: advanced 5577 5578 Note: 5579 The index sets map from row/col of permuted matrix to row/col of original matrix. 5580 The index sets should be on the same communicator as mat and have the same local sizes. 5581 5582 Developer Note: 5583 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5584 exploit the fact that row and col are permutations, consider implementing the 5585 more general `MatCreateSubMatrix()` instead. 5586 5587 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5588 @*/ 5589 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5590 { 5591 PetscFunctionBegin; 5592 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5593 PetscValidType(mat, 1); 5594 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5595 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5596 PetscAssertPointer(B, 4); 5597 PetscCheckSameComm(mat, 1, row, 2); 5598 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5599 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5600 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5601 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5602 MatCheckPreallocated(mat, 1); 5603 5604 if (mat->ops->permute) { 5605 PetscUseTypeMethod(mat, permute, row, col, B); 5606 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5607 } else { 5608 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5609 } 5610 PetscFunctionReturn(PETSC_SUCCESS); 5611 } 5612 5613 /*@ 5614 MatEqual - Compares two matrices. 5615 5616 Collective 5617 5618 Input Parameters: 5619 + A - the first matrix 5620 - B - the second matrix 5621 5622 Output Parameter: 5623 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5624 5625 Level: intermediate 5626 5627 Note: 5628 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 5629 using several randomly created vectors, see `MatMultEqual()`. 5630 5631 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5632 @*/ 5633 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5634 { 5635 PetscFunctionBegin; 5636 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5637 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5638 PetscValidType(A, 1); 5639 PetscValidType(B, 2); 5640 PetscAssertPointer(flg, 3); 5641 PetscCheckSameComm(A, 1, B, 2); 5642 MatCheckPreallocated(A, 1); 5643 MatCheckPreallocated(B, 2); 5644 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5645 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5646 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, 5647 B->cmap->N); 5648 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5649 PetscUseTypeMethod(A, equal, B, flg); 5650 } else { 5651 PetscCall(MatMultEqual(A, B, 10, flg)); 5652 } 5653 PetscFunctionReturn(PETSC_SUCCESS); 5654 } 5655 5656 /*@ 5657 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5658 matrices that are stored as vectors. Either of the two scaling 5659 matrices can be `NULL`. 5660 5661 Collective 5662 5663 Input Parameters: 5664 + mat - the matrix to be scaled 5665 . l - the left scaling vector (or `NULL`) 5666 - r - the right scaling vector (or `NULL`) 5667 5668 Level: intermediate 5669 5670 Note: 5671 `MatDiagonalScale()` computes $A = LAR$, where 5672 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5673 The L scales the rows of the matrix, the R scales the columns of the matrix. 5674 5675 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5676 @*/ 5677 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5678 { 5679 PetscFunctionBegin; 5680 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5681 PetscValidType(mat, 1); 5682 if (l) { 5683 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5684 PetscCheckSameComm(mat, 1, l, 2); 5685 } 5686 if (r) { 5687 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5688 PetscCheckSameComm(mat, 1, r, 3); 5689 } 5690 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5691 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5692 MatCheckPreallocated(mat, 1); 5693 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5694 5695 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5696 PetscUseTypeMethod(mat, diagonalscale, l, r); 5697 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5698 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5699 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5700 PetscFunctionReturn(PETSC_SUCCESS); 5701 } 5702 5703 /*@ 5704 MatScale - Scales all elements of a matrix by a given number. 5705 5706 Logically Collective 5707 5708 Input Parameters: 5709 + mat - the matrix to be scaled 5710 - a - the scaling value 5711 5712 Level: intermediate 5713 5714 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5715 @*/ 5716 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5717 { 5718 PetscFunctionBegin; 5719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5720 PetscValidType(mat, 1); 5721 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5722 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5723 PetscValidLogicalCollectiveScalar(mat, a, 2); 5724 MatCheckPreallocated(mat, 1); 5725 5726 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5727 if (a != (PetscScalar)1.0) { 5728 PetscUseTypeMethod(mat, scale, a); 5729 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5730 } 5731 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5732 PetscFunctionReturn(PETSC_SUCCESS); 5733 } 5734 5735 /*@ 5736 MatNorm - Calculates various norms of a matrix. 5737 5738 Collective 5739 5740 Input Parameters: 5741 + mat - the matrix 5742 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5743 5744 Output Parameter: 5745 . nrm - the resulting norm 5746 5747 Level: intermediate 5748 5749 .seealso: [](ch_matrices), `Mat` 5750 @*/ 5751 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5752 { 5753 PetscFunctionBegin; 5754 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5755 PetscValidType(mat, 1); 5756 PetscAssertPointer(nrm, 3); 5757 5758 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5759 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5760 MatCheckPreallocated(mat, 1); 5761 5762 PetscUseTypeMethod(mat, norm, type, nrm); 5763 PetscFunctionReturn(PETSC_SUCCESS); 5764 } 5765 5766 /* 5767 This variable is used to prevent counting of MatAssemblyBegin() that 5768 are called from within a MatAssemblyEnd(). 5769 */ 5770 static PetscInt MatAssemblyEnd_InUse = 0; 5771 /*@ 5772 MatAssemblyBegin - Begins assembling the matrix. This routine should 5773 be called after completing all calls to `MatSetValues()`. 5774 5775 Collective 5776 5777 Input Parameters: 5778 + mat - the matrix 5779 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5780 5781 Level: beginner 5782 5783 Notes: 5784 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5785 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5786 5787 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5788 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5789 using the matrix. 5790 5791 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5792 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 5793 a global collective operation requiring all processes that share the matrix. 5794 5795 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5796 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5797 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5798 5799 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5800 @*/ 5801 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5802 { 5803 PetscFunctionBegin; 5804 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5805 PetscValidType(mat, 1); 5806 MatCheckPreallocated(mat, 1); 5807 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5808 if (mat->assembled) { 5809 mat->was_assembled = PETSC_TRUE; 5810 mat->assembled = PETSC_FALSE; 5811 } 5812 5813 if (!MatAssemblyEnd_InUse) { 5814 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5815 PetscTryTypeMethod(mat, assemblybegin, type); 5816 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5817 } else PetscTryTypeMethod(mat, assemblybegin, type); 5818 PetscFunctionReturn(PETSC_SUCCESS); 5819 } 5820 5821 /*@ 5822 MatAssembled - Indicates if a matrix has been assembled and is ready for 5823 use; for example, in matrix-vector product. 5824 5825 Not Collective 5826 5827 Input Parameter: 5828 . mat - the matrix 5829 5830 Output Parameter: 5831 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5832 5833 Level: advanced 5834 5835 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5836 @*/ 5837 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5838 { 5839 PetscFunctionBegin; 5840 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5841 PetscAssertPointer(assembled, 2); 5842 *assembled = mat->assembled; 5843 PetscFunctionReturn(PETSC_SUCCESS); 5844 } 5845 5846 /*@ 5847 MatAssemblyEnd - Completes assembling the matrix. This routine should 5848 be called after `MatAssemblyBegin()`. 5849 5850 Collective 5851 5852 Input Parameters: 5853 + mat - the matrix 5854 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5855 5856 Options Database Keys: 5857 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5858 . -mat_view ::ascii_info_detail - Prints more detailed info 5859 . -mat_view - Prints matrix in ASCII format 5860 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5861 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5862 . -display <name> - Sets display name (default is host) 5863 . -draw_pause <sec> - Sets number of seconds to pause after display 5864 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5865 . -viewer_socket_machine <machine> - Machine to use for socket 5866 . -viewer_socket_port <port> - Port number to use for socket 5867 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5868 5869 Level: beginner 5870 5871 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5872 @*/ 5873 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5874 { 5875 static PetscInt inassm = 0; 5876 PetscBool flg = PETSC_FALSE; 5877 5878 PetscFunctionBegin; 5879 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5880 PetscValidType(mat, 1); 5881 5882 inassm++; 5883 MatAssemblyEnd_InUse++; 5884 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5885 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5886 PetscTryTypeMethod(mat, assemblyend, type); 5887 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5888 } else PetscTryTypeMethod(mat, assemblyend, type); 5889 5890 /* Flush assembly is not a true assembly */ 5891 if (type != MAT_FLUSH_ASSEMBLY) { 5892 if (mat->num_ass) { 5893 if (!mat->symmetry_eternal) { 5894 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5895 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5896 } 5897 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5898 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5899 } 5900 mat->num_ass++; 5901 mat->assembled = PETSC_TRUE; 5902 mat->ass_nonzerostate = mat->nonzerostate; 5903 } 5904 5905 mat->insertmode = NOT_SET_VALUES; 5906 MatAssemblyEnd_InUse--; 5907 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5908 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5909 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5910 5911 if (mat->checksymmetryonassembly) { 5912 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5913 if (flg) { 5914 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5915 } else { 5916 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5917 } 5918 } 5919 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5920 } 5921 inassm--; 5922 PetscFunctionReturn(PETSC_SUCCESS); 5923 } 5924 5925 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5926 /*@ 5927 MatSetOption - Sets a parameter option for a matrix. Some options 5928 may be specific to certain storage formats. Some options 5929 determine how values will be inserted (or added). Sorted, 5930 row-oriented input will generally assemble the fastest. The default 5931 is row-oriented. 5932 5933 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5934 5935 Input Parameters: 5936 + mat - the matrix 5937 . op - the option, one of those listed below (and possibly others), 5938 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5939 5940 Options Describing Matrix Structure: 5941 + `MAT_SPD` - symmetric positive definite 5942 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5943 . `MAT_HERMITIAN` - transpose is the complex conjugation 5944 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5945 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5946 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5947 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5948 5949 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5950 do not need to be computed (usually at a high cost) 5951 5952 Options For Use with `MatSetValues()`: 5953 Insert a logically dense subblock, which can be 5954 . `MAT_ROW_ORIENTED` - row-oriented (default) 5955 5956 These options reflect the data you pass in with `MatSetValues()`; it has 5957 nothing to do with how the data is stored internally in the matrix 5958 data structure. 5959 5960 When (re)assembling a matrix, we can restrict the input for 5961 efficiency/debugging purposes. These options include 5962 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5963 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5964 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5965 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5966 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5967 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5968 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5969 performance for very large process counts. 5970 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5971 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5972 functions, instead sending only neighbor messages. 5973 5974 Level: intermediate 5975 5976 Notes: 5977 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5978 5979 Some options are relevant only for particular matrix types and 5980 are thus ignored by others. Other options are not supported by 5981 certain matrix types and will generate an error message if set. 5982 5983 If using Fortran to compute a matrix, one may need to 5984 use the column-oriented option (or convert to the row-oriented 5985 format). 5986 5987 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5988 that would generate a new entry in the nonzero structure is instead 5989 ignored. Thus, if memory has not already been allocated for this particular 5990 data, then the insertion is ignored. For dense matrices, in which 5991 the entire array is allocated, no entries are ever ignored. 5992 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5993 5994 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5995 that would generate a new entry in the nonzero structure instead produces 5996 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 5997 5998 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5999 that would generate a new entry that has not been preallocated will 6000 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6001 only.) This is a useful flag when debugging matrix memory preallocation. 6002 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6003 6004 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6005 other processors should be dropped, rather than stashed. 6006 This is useful if you know that the "owning" processor is also 6007 always generating the correct matrix entries, so that PETSc need 6008 not transfer duplicate entries generated on another processor. 6009 6010 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6011 searches during matrix assembly. When this flag is set, the hash table 6012 is created during the first matrix assembly. This hash table is 6013 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6014 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6015 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6016 supported by `MATMPIBAIJ` format only. 6017 6018 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6019 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6020 6021 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6022 a zero location in the matrix 6023 6024 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6025 6026 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6027 zero row routines and thus improves performance for very large process counts. 6028 6029 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6030 part of the matrix (since they should match the upper triangular part). 6031 6032 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6033 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6034 with finite difference schemes with non-periodic boundary conditions. 6035 6036 Developer Note: 6037 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6038 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6039 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6040 not changed. 6041 6042 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6043 @*/ 6044 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6045 { 6046 PetscFunctionBegin; 6047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6048 if (op > 0) { 6049 PetscValidLogicalCollectiveEnum(mat, op, 2); 6050 PetscValidLogicalCollectiveBool(mat, flg, 3); 6051 } 6052 6053 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); 6054 6055 switch (op) { 6056 case MAT_FORCE_DIAGONAL_ENTRIES: 6057 mat->force_diagonals = flg; 6058 PetscFunctionReturn(PETSC_SUCCESS); 6059 case MAT_NO_OFF_PROC_ENTRIES: 6060 mat->nooffprocentries = flg; 6061 PetscFunctionReturn(PETSC_SUCCESS); 6062 case MAT_SUBSET_OFF_PROC_ENTRIES: 6063 mat->assembly_subset = flg; 6064 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6065 #if !defined(PETSC_HAVE_MPIUNI) 6066 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6067 #endif 6068 mat->stash.first_assembly_done = PETSC_FALSE; 6069 } 6070 PetscFunctionReturn(PETSC_SUCCESS); 6071 case MAT_NO_OFF_PROC_ZERO_ROWS: 6072 mat->nooffproczerorows = flg; 6073 PetscFunctionReturn(PETSC_SUCCESS); 6074 case MAT_SPD: 6075 if (flg) { 6076 mat->spd = PETSC_BOOL3_TRUE; 6077 mat->symmetric = PETSC_BOOL3_TRUE; 6078 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6079 } else { 6080 mat->spd = PETSC_BOOL3_FALSE; 6081 } 6082 break; 6083 case MAT_SYMMETRIC: 6084 mat->symmetric = PetscBoolToBool3(flg); 6085 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6086 #if !defined(PETSC_USE_COMPLEX) 6087 mat->hermitian = PetscBoolToBool3(flg); 6088 #endif 6089 break; 6090 case MAT_HERMITIAN: 6091 mat->hermitian = PetscBoolToBool3(flg); 6092 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6093 #if !defined(PETSC_USE_COMPLEX) 6094 mat->symmetric = PetscBoolToBool3(flg); 6095 #endif 6096 break; 6097 case MAT_STRUCTURALLY_SYMMETRIC: 6098 mat->structurally_symmetric = PetscBoolToBool3(flg); 6099 break; 6100 case MAT_SYMMETRY_ETERNAL: 6101 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"); 6102 mat->symmetry_eternal = flg; 6103 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6104 break; 6105 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6106 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"); 6107 mat->structural_symmetry_eternal = flg; 6108 break; 6109 case MAT_SPD_ETERNAL: 6110 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"); 6111 mat->spd_eternal = flg; 6112 if (flg) { 6113 mat->structural_symmetry_eternal = PETSC_TRUE; 6114 mat->symmetry_eternal = PETSC_TRUE; 6115 } 6116 break; 6117 case MAT_STRUCTURE_ONLY: 6118 mat->structure_only = flg; 6119 break; 6120 case MAT_SORTED_FULL: 6121 mat->sortedfull = flg; 6122 break; 6123 default: 6124 break; 6125 } 6126 PetscTryTypeMethod(mat, setoption, op, flg); 6127 PetscFunctionReturn(PETSC_SUCCESS); 6128 } 6129 6130 /*@ 6131 MatGetOption - Gets a parameter option that has been set for a matrix. 6132 6133 Logically Collective 6134 6135 Input Parameters: 6136 + mat - the matrix 6137 - op - the option, this only responds to certain options, check the code for which ones 6138 6139 Output Parameter: 6140 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6141 6142 Level: intermediate 6143 6144 Notes: 6145 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6146 6147 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6148 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6149 6150 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6151 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6152 @*/ 6153 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6154 { 6155 PetscFunctionBegin; 6156 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6157 PetscValidType(mat, 1); 6158 6159 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); 6160 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()"); 6161 6162 switch (op) { 6163 case MAT_NO_OFF_PROC_ENTRIES: 6164 *flg = mat->nooffprocentries; 6165 break; 6166 case MAT_NO_OFF_PROC_ZERO_ROWS: 6167 *flg = mat->nooffproczerorows; 6168 break; 6169 case MAT_SYMMETRIC: 6170 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6171 break; 6172 case MAT_HERMITIAN: 6173 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6174 break; 6175 case MAT_STRUCTURALLY_SYMMETRIC: 6176 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6177 break; 6178 case MAT_SPD: 6179 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6180 break; 6181 case MAT_SYMMETRY_ETERNAL: 6182 *flg = mat->symmetry_eternal; 6183 break; 6184 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6185 *flg = mat->symmetry_eternal; 6186 break; 6187 default: 6188 break; 6189 } 6190 PetscFunctionReturn(PETSC_SUCCESS); 6191 } 6192 6193 /*@ 6194 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6195 this routine retains the old nonzero structure. 6196 6197 Logically Collective 6198 6199 Input Parameter: 6200 . mat - the matrix 6201 6202 Level: intermediate 6203 6204 Note: 6205 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. 6206 See the Performance chapter of the users manual for information on preallocating matrices. 6207 6208 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6209 @*/ 6210 PetscErrorCode MatZeroEntries(Mat mat) 6211 { 6212 PetscFunctionBegin; 6213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6214 PetscValidType(mat, 1); 6215 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6216 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"); 6217 MatCheckPreallocated(mat, 1); 6218 6219 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6220 PetscUseTypeMethod(mat, zeroentries); 6221 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6222 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6223 PetscFunctionReturn(PETSC_SUCCESS); 6224 } 6225 6226 /*@ 6227 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6228 of a set of rows and columns of a matrix. 6229 6230 Collective 6231 6232 Input Parameters: 6233 + mat - the matrix 6234 . numRows - the number of rows/columns to zero 6235 . rows - the global row indices 6236 . diag - value put in the diagonal of the eliminated rows 6237 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6238 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6239 6240 Level: intermediate 6241 6242 Notes: 6243 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6244 6245 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6246 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 6247 6248 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6249 Krylov method to take advantage of the known solution on the zeroed rows. 6250 6251 For the parallel case, all processes that share the matrix (i.e., 6252 those in the communicator used for matrix creation) MUST call this 6253 routine, regardless of whether any rows being zeroed are owned by 6254 them. 6255 6256 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6257 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 6258 missing. 6259 6260 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6261 list only rows local to itself). 6262 6263 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6264 6265 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6266 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6267 @*/ 6268 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6269 { 6270 PetscFunctionBegin; 6271 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6272 PetscValidType(mat, 1); 6273 if (numRows) PetscAssertPointer(rows, 3); 6274 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6275 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6276 MatCheckPreallocated(mat, 1); 6277 6278 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6279 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6280 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6281 PetscFunctionReturn(PETSC_SUCCESS); 6282 } 6283 6284 /*@ 6285 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6286 of a set of rows and columns of a matrix. 6287 6288 Collective 6289 6290 Input Parameters: 6291 + mat - the matrix 6292 . is - the rows to zero 6293 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6294 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6295 - b - optional vector of right-hand side, that will be adjusted by provided solution 6296 6297 Level: intermediate 6298 6299 Note: 6300 See `MatZeroRowsColumns()` for details on how this routine operates. 6301 6302 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6303 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6304 @*/ 6305 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6306 { 6307 PetscInt numRows; 6308 const PetscInt *rows; 6309 6310 PetscFunctionBegin; 6311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6312 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6313 PetscValidType(mat, 1); 6314 PetscValidType(is, 2); 6315 PetscCall(ISGetLocalSize(is, &numRows)); 6316 PetscCall(ISGetIndices(is, &rows)); 6317 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6318 PetscCall(ISRestoreIndices(is, &rows)); 6319 PetscFunctionReturn(PETSC_SUCCESS); 6320 } 6321 6322 /*@ 6323 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6324 of a set of rows of a matrix. 6325 6326 Collective 6327 6328 Input Parameters: 6329 + mat - the matrix 6330 . numRows - the number of rows to zero 6331 . rows - the global row indices 6332 . diag - value put in the diagonal of the zeroed rows 6333 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6334 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6335 6336 Level: intermediate 6337 6338 Notes: 6339 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6340 6341 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6342 6343 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6344 Krylov method to take advantage of the known solution on the zeroed rows. 6345 6346 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) 6347 from the matrix. 6348 6349 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6350 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6351 formats this does not alter the nonzero structure. 6352 6353 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6354 of the matrix is not changed the values are 6355 merely zeroed. 6356 6357 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6358 formats can optionally remove the main diagonal entry from the 6359 nonzero structure as well, by passing 0.0 as the final argument). 6360 6361 For the parallel case, all processes that share the matrix (i.e., 6362 those in the communicator used for matrix creation) MUST call this 6363 routine, regardless of whether any rows being zeroed are owned by 6364 them. 6365 6366 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6367 list only rows local to itself). 6368 6369 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6370 owns that are to be zeroed. This saves a global synchronization in the implementation. 6371 6372 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6373 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6374 @*/ 6375 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6376 { 6377 PetscFunctionBegin; 6378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6379 PetscValidType(mat, 1); 6380 if (numRows) PetscAssertPointer(rows, 3); 6381 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6382 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6383 MatCheckPreallocated(mat, 1); 6384 6385 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6386 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6387 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6388 PetscFunctionReturn(PETSC_SUCCESS); 6389 } 6390 6391 /*@ 6392 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6393 of a set of rows of a matrix indicated by an `IS` 6394 6395 Collective 6396 6397 Input Parameters: 6398 + mat - the matrix 6399 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6400 . diag - value put in all diagonals of eliminated rows 6401 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6402 - b - optional vector of right-hand side, that will be adjusted by provided solution 6403 6404 Level: intermediate 6405 6406 Note: 6407 See `MatZeroRows()` for details on how this routine operates. 6408 6409 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6410 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6411 @*/ 6412 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6413 { 6414 PetscInt numRows = 0; 6415 const PetscInt *rows = NULL; 6416 6417 PetscFunctionBegin; 6418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6419 PetscValidType(mat, 1); 6420 if (is) { 6421 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6422 PetscCall(ISGetLocalSize(is, &numRows)); 6423 PetscCall(ISGetIndices(is, &rows)); 6424 } 6425 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6426 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6427 PetscFunctionReturn(PETSC_SUCCESS); 6428 } 6429 6430 /*@ 6431 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6432 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6433 6434 Collective 6435 6436 Input Parameters: 6437 + mat - the matrix 6438 . numRows - the number of rows to remove 6439 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6440 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6441 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6442 - b - optional vector of right-hand side, that will be adjusted by provided solution 6443 6444 Level: intermediate 6445 6446 Notes: 6447 See `MatZeroRows()` for details on how this routine operates. 6448 6449 The grid coordinates are across the entire grid, not just the local portion 6450 6451 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6452 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6453 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6454 `DM_BOUNDARY_PERIODIC` boundary type. 6455 6456 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 6457 a single value per point) you can skip filling those indices. 6458 6459 Fortran Note: 6460 `idxm` and `idxn` should be declared as 6461 .vb 6462 MatStencil idxm(4, m) 6463 .ve 6464 and the values inserted using 6465 .vb 6466 idxm(MatStencil_i, 1) = i 6467 idxm(MatStencil_j, 1) = j 6468 idxm(MatStencil_k, 1) = k 6469 idxm(MatStencil_c, 1) = c 6470 etc 6471 .ve 6472 6473 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6474 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6475 @*/ 6476 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6477 { 6478 PetscInt dim = mat->stencil.dim; 6479 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6480 PetscInt *dims = mat->stencil.dims + 1; 6481 PetscInt *starts = mat->stencil.starts; 6482 PetscInt *dxm = (PetscInt *)rows; 6483 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6484 6485 PetscFunctionBegin; 6486 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6487 PetscValidType(mat, 1); 6488 if (numRows) PetscAssertPointer(rows, 3); 6489 6490 PetscCall(PetscMalloc1(numRows, &jdxm)); 6491 for (i = 0; i < numRows; ++i) { 6492 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6493 for (j = 0; j < 3 - sdim; ++j) dxm++; 6494 /* Local index in X dir */ 6495 tmp = *dxm++ - starts[0]; 6496 /* Loop over remaining dimensions */ 6497 for (j = 0; j < dim - 1; ++j) { 6498 /* If nonlocal, set index to be negative */ 6499 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6500 /* Update local index */ 6501 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6502 } 6503 /* Skip component slot if necessary */ 6504 if (mat->stencil.noc) dxm++; 6505 /* Local row number */ 6506 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6507 } 6508 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6509 PetscCall(PetscFree(jdxm)); 6510 PetscFunctionReturn(PETSC_SUCCESS); 6511 } 6512 6513 /*@ 6514 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6515 of a set of rows and columns of a matrix. 6516 6517 Collective 6518 6519 Input Parameters: 6520 + mat - the matrix 6521 . numRows - the number of rows/columns to remove 6522 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6523 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6524 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6525 - b - optional vector of right-hand side, that will be adjusted by provided solution 6526 6527 Level: intermediate 6528 6529 Notes: 6530 See `MatZeroRowsColumns()` for details on how this routine operates. 6531 6532 The grid coordinates are across the entire grid, not just the local portion 6533 6534 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6535 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6536 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6537 `DM_BOUNDARY_PERIODIC` boundary type. 6538 6539 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 6540 a single value per point) you can skip filling those indices. 6541 6542 Fortran Note: 6543 `idxm` and `idxn` should be declared as 6544 .vb 6545 MatStencil idxm(4, m) 6546 .ve 6547 and the values inserted using 6548 .vb 6549 idxm(MatStencil_i, 1) = i 6550 idxm(MatStencil_j, 1) = j 6551 idxm(MatStencil_k, 1) = k 6552 idxm(MatStencil_c, 1) = c 6553 etc 6554 .ve 6555 6556 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6557 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6558 @*/ 6559 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6560 { 6561 PetscInt dim = mat->stencil.dim; 6562 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6563 PetscInt *dims = mat->stencil.dims + 1; 6564 PetscInt *starts = mat->stencil.starts; 6565 PetscInt *dxm = (PetscInt *)rows; 6566 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6567 6568 PetscFunctionBegin; 6569 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6570 PetscValidType(mat, 1); 6571 if (numRows) PetscAssertPointer(rows, 3); 6572 6573 PetscCall(PetscMalloc1(numRows, &jdxm)); 6574 for (i = 0; i < numRows; ++i) { 6575 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6576 for (j = 0; j < 3 - sdim; ++j) dxm++; 6577 /* Local index in X dir */ 6578 tmp = *dxm++ - starts[0]; 6579 /* Loop over remaining dimensions */ 6580 for (j = 0; j < dim - 1; ++j) { 6581 /* If nonlocal, set index to be negative */ 6582 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6583 /* Update local index */ 6584 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6585 } 6586 /* Skip component slot if necessary */ 6587 if (mat->stencil.noc) dxm++; 6588 /* Local row number */ 6589 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6590 } 6591 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6592 PetscCall(PetscFree(jdxm)); 6593 PetscFunctionReturn(PETSC_SUCCESS); 6594 } 6595 6596 /*@ 6597 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6598 of a set of rows of a matrix; using local numbering of rows. 6599 6600 Collective 6601 6602 Input Parameters: 6603 + mat - the matrix 6604 . numRows - the number of rows to remove 6605 . rows - the local row indices 6606 . diag - value put in all diagonals of eliminated rows 6607 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6608 - b - optional vector of right-hand side, that will be adjusted by provided solution 6609 6610 Level: intermediate 6611 6612 Notes: 6613 Before calling `MatZeroRowsLocal()`, the user must first set the 6614 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6615 6616 See `MatZeroRows()` for details on how this routine operates. 6617 6618 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6619 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6620 @*/ 6621 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6622 { 6623 PetscFunctionBegin; 6624 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6625 PetscValidType(mat, 1); 6626 if (numRows) PetscAssertPointer(rows, 3); 6627 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6628 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6629 MatCheckPreallocated(mat, 1); 6630 6631 if (mat->ops->zerorowslocal) { 6632 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6633 } else { 6634 IS is, newis; 6635 const PetscInt *newRows; 6636 6637 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6638 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6639 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6640 PetscCall(ISGetIndices(newis, &newRows)); 6641 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6642 PetscCall(ISRestoreIndices(newis, &newRows)); 6643 PetscCall(ISDestroy(&newis)); 6644 PetscCall(ISDestroy(&is)); 6645 } 6646 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6647 PetscFunctionReturn(PETSC_SUCCESS); 6648 } 6649 6650 /*@ 6651 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6652 of a set of rows of a matrix; using local numbering of rows. 6653 6654 Collective 6655 6656 Input Parameters: 6657 + mat - the matrix 6658 . is - index set of rows to remove 6659 . diag - value put in all diagonals of eliminated rows 6660 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6661 - b - optional vector of right-hand side, that will be adjusted by provided solution 6662 6663 Level: intermediate 6664 6665 Notes: 6666 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6667 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6668 6669 See `MatZeroRows()` for details on how this routine operates. 6670 6671 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6672 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6673 @*/ 6674 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6675 { 6676 PetscInt numRows; 6677 const PetscInt *rows; 6678 6679 PetscFunctionBegin; 6680 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6681 PetscValidType(mat, 1); 6682 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6683 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6684 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6685 MatCheckPreallocated(mat, 1); 6686 6687 PetscCall(ISGetLocalSize(is, &numRows)); 6688 PetscCall(ISGetIndices(is, &rows)); 6689 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6690 PetscCall(ISRestoreIndices(is, &rows)); 6691 PetscFunctionReturn(PETSC_SUCCESS); 6692 } 6693 6694 /*@ 6695 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6696 of a set of rows and columns of a matrix; using local numbering of rows. 6697 6698 Collective 6699 6700 Input Parameters: 6701 + mat - the matrix 6702 . numRows - the number of rows to remove 6703 . rows - the global row indices 6704 . diag - value put in all diagonals of eliminated rows 6705 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6706 - b - optional vector of right-hand side, that will be adjusted by provided solution 6707 6708 Level: intermediate 6709 6710 Notes: 6711 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6712 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6713 6714 See `MatZeroRowsColumns()` for details on how this routine operates. 6715 6716 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6717 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6718 @*/ 6719 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6720 { 6721 IS is, newis; 6722 const PetscInt *newRows; 6723 6724 PetscFunctionBegin; 6725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6726 PetscValidType(mat, 1); 6727 if (numRows) PetscAssertPointer(rows, 3); 6728 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6729 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6730 MatCheckPreallocated(mat, 1); 6731 6732 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6733 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6734 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6735 PetscCall(ISGetIndices(newis, &newRows)); 6736 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6737 PetscCall(ISRestoreIndices(newis, &newRows)); 6738 PetscCall(ISDestroy(&newis)); 6739 PetscCall(ISDestroy(&is)); 6740 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6741 PetscFunctionReturn(PETSC_SUCCESS); 6742 } 6743 6744 /*@ 6745 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6746 of a set of rows and columns of a matrix; using local numbering of rows. 6747 6748 Collective 6749 6750 Input Parameters: 6751 + mat - the matrix 6752 . is - index set of rows to remove 6753 . diag - value put in all diagonals of eliminated rows 6754 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6755 - b - optional vector of right-hand side, that will be adjusted by provided solution 6756 6757 Level: intermediate 6758 6759 Notes: 6760 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6761 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6762 6763 See `MatZeroRowsColumns()` for details on how this routine operates. 6764 6765 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6766 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6767 @*/ 6768 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6769 { 6770 PetscInt numRows; 6771 const PetscInt *rows; 6772 6773 PetscFunctionBegin; 6774 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6775 PetscValidType(mat, 1); 6776 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6777 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6778 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6779 MatCheckPreallocated(mat, 1); 6780 6781 PetscCall(ISGetLocalSize(is, &numRows)); 6782 PetscCall(ISGetIndices(is, &rows)); 6783 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6784 PetscCall(ISRestoreIndices(is, &rows)); 6785 PetscFunctionReturn(PETSC_SUCCESS); 6786 } 6787 6788 /*@ 6789 MatGetSize - Returns the numbers of rows and columns in a matrix. 6790 6791 Not Collective 6792 6793 Input Parameter: 6794 . mat - the matrix 6795 6796 Output Parameters: 6797 + m - the number of global rows 6798 - n - the number of global columns 6799 6800 Level: beginner 6801 6802 Note: 6803 Both output parameters can be `NULL` on input. 6804 6805 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6806 @*/ 6807 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6808 { 6809 PetscFunctionBegin; 6810 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6811 if (m) *m = mat->rmap->N; 6812 if (n) *n = mat->cmap->N; 6813 PetscFunctionReturn(PETSC_SUCCESS); 6814 } 6815 6816 /*@ 6817 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6818 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6819 6820 Not Collective 6821 6822 Input Parameter: 6823 . mat - the matrix 6824 6825 Output Parameters: 6826 + m - the number of local rows, use `NULL` to not obtain this value 6827 - n - the number of local columns, use `NULL` to not obtain this value 6828 6829 Level: beginner 6830 6831 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6832 @*/ 6833 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6834 { 6835 PetscFunctionBegin; 6836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6837 if (m) PetscAssertPointer(m, 2); 6838 if (n) PetscAssertPointer(n, 3); 6839 if (m) *m = mat->rmap->n; 6840 if (n) *n = mat->cmap->n; 6841 PetscFunctionReturn(PETSC_SUCCESS); 6842 } 6843 6844 /*@ 6845 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6846 vector one multiplies this matrix by that are owned by this processor. 6847 6848 Not Collective, unless matrix has not been allocated, then collective 6849 6850 Input Parameter: 6851 . mat - the matrix 6852 6853 Output Parameters: 6854 + m - the global index of the first local column, use `NULL` to not obtain this value 6855 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6856 6857 Level: developer 6858 6859 Notes: 6860 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6861 6862 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6863 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6864 6865 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6866 the local values in the matrix. 6867 6868 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6869 Layouts](sec_matlayout) for details on matrix layouts. 6870 6871 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6872 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6873 @*/ 6874 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6875 { 6876 PetscFunctionBegin; 6877 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6878 PetscValidType(mat, 1); 6879 if (m) PetscAssertPointer(m, 2); 6880 if (n) PetscAssertPointer(n, 3); 6881 MatCheckPreallocated(mat, 1); 6882 if (m) *m = mat->cmap->rstart; 6883 if (n) *n = mat->cmap->rend; 6884 PetscFunctionReturn(PETSC_SUCCESS); 6885 } 6886 6887 /*@ 6888 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6889 this MPI process. 6890 6891 Not Collective 6892 6893 Input Parameter: 6894 . mat - the matrix 6895 6896 Output Parameters: 6897 + m - the global index of the first local row, use `NULL` to not obtain this value 6898 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6899 6900 Level: beginner 6901 6902 Notes: 6903 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6904 6905 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6906 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6907 6908 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6909 the local values in the matrix. 6910 6911 The high argument is one more than the last element stored locally. 6912 6913 For all matrices it returns the range of matrix rows associated with rows of a vector that 6914 would contain the result of a matrix vector product with this matrix. See [Matrix 6915 Layouts](sec_matlayout) for details on matrix layouts. 6916 6917 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6918 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6919 @*/ 6920 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6921 { 6922 PetscFunctionBegin; 6923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6924 PetscValidType(mat, 1); 6925 if (m) PetscAssertPointer(m, 2); 6926 if (n) PetscAssertPointer(n, 3); 6927 MatCheckPreallocated(mat, 1); 6928 if (m) *m = mat->rmap->rstart; 6929 if (n) *n = mat->rmap->rend; 6930 PetscFunctionReturn(PETSC_SUCCESS); 6931 } 6932 6933 /*@C 6934 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6935 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6936 6937 Not Collective, unless matrix has not been allocated 6938 6939 Input Parameter: 6940 . mat - the matrix 6941 6942 Output Parameter: 6943 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6944 where `size` is the number of MPI processes used by `mat` 6945 6946 Level: beginner 6947 6948 Notes: 6949 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6950 6951 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6952 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6953 6954 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6955 the local values in the matrix. 6956 6957 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6958 would contain the result of a matrix vector product with this matrix. See [Matrix 6959 Layouts](sec_matlayout) for details on matrix layouts. 6960 6961 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6962 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6963 `DMDAGetGhostCorners()`, `DM` 6964 @*/ 6965 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6966 { 6967 PetscFunctionBegin; 6968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6969 PetscValidType(mat, 1); 6970 MatCheckPreallocated(mat, 1); 6971 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6972 PetscFunctionReturn(PETSC_SUCCESS); 6973 } 6974 6975 /*@C 6976 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6977 vector one multiplies this vector by that are owned by each processor. 6978 6979 Not Collective, unless matrix has not been allocated 6980 6981 Input Parameter: 6982 . mat - the matrix 6983 6984 Output Parameter: 6985 . ranges - start of each processors portion plus one more than the total length at the end 6986 6987 Level: beginner 6988 6989 Notes: 6990 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6991 6992 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6993 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6994 6995 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6996 the local values in the matrix. 6997 6998 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6999 Layouts](sec_matlayout) for details on matrix layouts. 7000 7001 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7002 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7003 `DMDAGetGhostCorners()`, `DM` 7004 @*/ 7005 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7006 { 7007 PetscFunctionBegin; 7008 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7009 PetscValidType(mat, 1); 7010 MatCheckPreallocated(mat, 1); 7011 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7012 PetscFunctionReturn(PETSC_SUCCESS); 7013 } 7014 7015 /*@ 7016 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7017 7018 Not Collective 7019 7020 Input Parameter: 7021 . A - matrix 7022 7023 Output Parameters: 7024 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7025 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7026 7027 Level: intermediate 7028 7029 Note: 7030 You should call `ISDestroy()` on the returned `IS` 7031 7032 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7033 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7034 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7035 details on matrix layouts. 7036 7037 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7038 @*/ 7039 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7040 { 7041 PetscErrorCode (*f)(Mat, IS *, IS *); 7042 7043 PetscFunctionBegin; 7044 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7045 PetscValidType(A, 1); 7046 MatCheckPreallocated(A, 1); 7047 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7048 if (f) { 7049 PetscCall((*f)(A, rows, cols)); 7050 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7051 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7052 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7053 } 7054 PetscFunctionReturn(PETSC_SUCCESS); 7055 } 7056 7057 /*@ 7058 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7059 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7060 to complete the factorization. 7061 7062 Collective 7063 7064 Input Parameters: 7065 + fact - the factorized matrix obtained with `MatGetFactor()` 7066 . mat - the matrix 7067 . row - row permutation 7068 . col - column permutation 7069 - info - structure containing 7070 .vb 7071 levels - number of levels of fill. 7072 expected fill - as ratio of original fill. 7073 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7074 missing diagonal entries) 7075 .ve 7076 7077 Level: developer 7078 7079 Notes: 7080 See [Matrix Factorization](sec_matfactor) for additional information. 7081 7082 Most users should employ the `KSP` interface for linear solvers 7083 instead of working directly with matrix algebra routines such as this. 7084 See, e.g., `KSPCreate()`. 7085 7086 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7087 7088 Fortran Note: 7089 A valid (non-null) `info` argument must be provided 7090 7091 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7092 `MatGetOrdering()`, `MatFactorInfo` 7093 @*/ 7094 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7095 { 7096 PetscFunctionBegin; 7097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7098 PetscValidType(mat, 2); 7099 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7100 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7101 PetscAssertPointer(info, 5); 7102 PetscAssertPointer(fact, 1); 7103 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7104 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7105 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7106 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7107 MatCheckPreallocated(mat, 2); 7108 7109 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7110 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7111 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7112 PetscFunctionReturn(PETSC_SUCCESS); 7113 } 7114 7115 /*@ 7116 MatICCFactorSymbolic - Performs symbolic incomplete 7117 Cholesky factorization for a symmetric matrix. Use 7118 `MatCholeskyFactorNumeric()` to complete the factorization. 7119 7120 Collective 7121 7122 Input Parameters: 7123 + fact - the factorized matrix obtained with `MatGetFactor()` 7124 . mat - the matrix to be factored 7125 . perm - row and column permutation 7126 - info - structure containing 7127 .vb 7128 levels - number of levels of fill. 7129 expected fill - as ratio of original fill. 7130 .ve 7131 7132 Level: developer 7133 7134 Notes: 7135 Most users should employ the `KSP` interface for linear solvers 7136 instead of working directly with matrix algebra routines such as this. 7137 See, e.g., `KSPCreate()`. 7138 7139 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7140 7141 Fortran Note: 7142 A valid (non-null) `info` argument must be provided 7143 7144 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7145 @*/ 7146 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7147 { 7148 PetscFunctionBegin; 7149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7150 PetscValidType(mat, 2); 7151 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7152 PetscAssertPointer(info, 4); 7153 PetscAssertPointer(fact, 1); 7154 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7155 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7156 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7157 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7158 MatCheckPreallocated(mat, 2); 7159 7160 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7161 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7162 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7163 PetscFunctionReturn(PETSC_SUCCESS); 7164 } 7165 7166 /*@C 7167 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7168 points to an array of valid matrices, they may be reused to store the new 7169 submatrices. 7170 7171 Collective 7172 7173 Input Parameters: 7174 + mat - the matrix 7175 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7176 . irow - index set of rows to extract 7177 . icol - index set of columns to extract 7178 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7179 7180 Output Parameter: 7181 . submat - the array of submatrices 7182 7183 Level: advanced 7184 7185 Notes: 7186 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7187 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7188 to extract a parallel submatrix. 7189 7190 Some matrix types place restrictions on the row and column 7191 indices, such as that they be sorted or that they be equal to each other. 7192 7193 The index sets may not have duplicate entries. 7194 7195 When extracting submatrices from a parallel matrix, each processor can 7196 form a different submatrix by setting the rows and columns of its 7197 individual index sets according to the local submatrix desired. 7198 7199 When finished using the submatrices, the user should destroy 7200 them with `MatDestroySubMatrices()`. 7201 7202 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7203 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7204 7205 This routine creates the matrices in submat; you should NOT create them before 7206 calling it. It also allocates the array of matrix pointers submat. 7207 7208 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7209 request one row/column in a block, they must request all rows/columns that are in 7210 that block. For example, if the block size is 2 you cannot request just row 0 and 7211 column 0. 7212 7213 Fortran Note: 7214 .vb 7215 Mat, pointer :: submat(:) 7216 .ve 7217 7218 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7219 @*/ 7220 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7221 { 7222 PetscInt i; 7223 PetscBool eq; 7224 7225 PetscFunctionBegin; 7226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7227 PetscValidType(mat, 1); 7228 if (n) { 7229 PetscAssertPointer(irow, 3); 7230 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7231 PetscAssertPointer(icol, 4); 7232 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7233 } 7234 PetscAssertPointer(submat, 6); 7235 if (n && scall == MAT_REUSE_MATRIX) { 7236 PetscAssertPointer(*submat, 6); 7237 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7238 } 7239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7240 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7241 MatCheckPreallocated(mat, 1); 7242 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7243 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7244 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7245 for (i = 0; i < n; i++) { 7246 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7247 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7248 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7249 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7250 if (mat->boundtocpu && mat->bindingpropagates) { 7251 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7252 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7253 } 7254 #endif 7255 } 7256 PetscFunctionReturn(PETSC_SUCCESS); 7257 } 7258 7259 /*@C 7260 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7261 7262 Collective 7263 7264 Input Parameters: 7265 + mat - the matrix 7266 . n - the number of submatrixes to be extracted 7267 . irow - index set of rows to extract 7268 . icol - index set of columns to extract 7269 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7270 7271 Output Parameter: 7272 . submat - the array of submatrices 7273 7274 Level: advanced 7275 7276 Note: 7277 This is used by `PCGASM` 7278 7279 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7280 @*/ 7281 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7282 { 7283 PetscInt i; 7284 PetscBool eq; 7285 7286 PetscFunctionBegin; 7287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7288 PetscValidType(mat, 1); 7289 if (n) { 7290 PetscAssertPointer(irow, 3); 7291 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7292 PetscAssertPointer(icol, 4); 7293 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7294 } 7295 PetscAssertPointer(submat, 6); 7296 if (n && scall == MAT_REUSE_MATRIX) { 7297 PetscAssertPointer(*submat, 6); 7298 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7299 } 7300 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7301 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7302 MatCheckPreallocated(mat, 1); 7303 7304 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7305 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7306 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7307 for (i = 0; i < n; i++) { 7308 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7309 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7310 } 7311 PetscFunctionReturn(PETSC_SUCCESS); 7312 } 7313 7314 /*@C 7315 MatDestroyMatrices - Destroys an array of matrices 7316 7317 Collective 7318 7319 Input Parameters: 7320 + n - the number of local matrices 7321 - mat - the matrices (this is a pointer to the array of matrices) 7322 7323 Level: advanced 7324 7325 Notes: 7326 Frees not only the matrices, but also the array that contains the matrices 7327 7328 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7329 7330 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7331 @*/ 7332 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7333 { 7334 PetscInt i; 7335 7336 PetscFunctionBegin; 7337 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7338 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7339 PetscAssertPointer(mat, 2); 7340 7341 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7342 7343 /* memory is allocated even if n = 0 */ 7344 PetscCall(PetscFree(*mat)); 7345 PetscFunctionReturn(PETSC_SUCCESS); 7346 } 7347 7348 /*@C 7349 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7350 7351 Collective 7352 7353 Input Parameters: 7354 + n - the number of local matrices 7355 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7356 7357 Level: advanced 7358 7359 Note: 7360 Frees not only the matrices, but also the array that contains the matrices 7361 7362 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7363 @*/ 7364 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7365 { 7366 Mat mat0; 7367 7368 PetscFunctionBegin; 7369 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7370 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7371 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7372 PetscAssertPointer(mat, 2); 7373 7374 mat0 = (*mat)[0]; 7375 if (mat0 && mat0->ops->destroysubmatrices) { 7376 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7377 } else { 7378 PetscCall(MatDestroyMatrices(n, mat)); 7379 } 7380 PetscFunctionReturn(PETSC_SUCCESS); 7381 } 7382 7383 /*@ 7384 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7385 7386 Collective 7387 7388 Input Parameter: 7389 . mat - the matrix 7390 7391 Output Parameter: 7392 . matstruct - the sequential matrix with the nonzero structure of `mat` 7393 7394 Level: developer 7395 7396 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7397 @*/ 7398 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7399 { 7400 PetscFunctionBegin; 7401 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7402 PetscAssertPointer(matstruct, 2); 7403 7404 PetscValidType(mat, 1); 7405 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7406 MatCheckPreallocated(mat, 1); 7407 7408 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7409 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7410 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7411 PetscFunctionReturn(PETSC_SUCCESS); 7412 } 7413 7414 /*@C 7415 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7416 7417 Collective 7418 7419 Input Parameter: 7420 . mat - the matrix 7421 7422 Level: advanced 7423 7424 Note: 7425 This is not needed, one can just call `MatDestroy()` 7426 7427 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7428 @*/ 7429 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7430 { 7431 PetscFunctionBegin; 7432 PetscAssertPointer(mat, 1); 7433 PetscCall(MatDestroy(mat)); 7434 PetscFunctionReturn(PETSC_SUCCESS); 7435 } 7436 7437 /*@ 7438 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7439 replaces the index sets by larger ones that represent submatrices with 7440 additional overlap. 7441 7442 Collective 7443 7444 Input Parameters: 7445 + mat - the matrix 7446 . n - the number of index sets 7447 . is - the array of index sets (these index sets will changed during the call) 7448 - ov - the additional overlap requested 7449 7450 Options Database Key: 7451 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7452 7453 Level: developer 7454 7455 Note: 7456 The computed overlap preserves the matrix block sizes when the blocks are square. 7457 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7458 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7459 7460 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7461 @*/ 7462 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7463 { 7464 PetscInt i, bs, cbs; 7465 7466 PetscFunctionBegin; 7467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7468 PetscValidType(mat, 1); 7469 PetscValidLogicalCollectiveInt(mat, n, 2); 7470 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7471 if (n) { 7472 PetscAssertPointer(is, 3); 7473 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7474 } 7475 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7476 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7477 MatCheckPreallocated(mat, 1); 7478 7479 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7480 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7481 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7482 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7483 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7484 if (bs == cbs) { 7485 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7486 } 7487 PetscFunctionReturn(PETSC_SUCCESS); 7488 } 7489 7490 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7491 7492 /*@ 7493 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7494 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7495 additional overlap. 7496 7497 Collective 7498 7499 Input Parameters: 7500 + mat - the matrix 7501 . n - the number of index sets 7502 . is - the array of index sets (these index sets will changed during the call) 7503 - ov - the additional overlap requested 7504 7505 ` Options Database Key: 7506 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7507 7508 Level: developer 7509 7510 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7511 @*/ 7512 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7513 { 7514 PetscInt i; 7515 7516 PetscFunctionBegin; 7517 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7518 PetscValidType(mat, 1); 7519 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7520 if (n) { 7521 PetscAssertPointer(is, 3); 7522 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7523 } 7524 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7525 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7526 MatCheckPreallocated(mat, 1); 7527 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7528 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7529 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7530 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7531 PetscFunctionReturn(PETSC_SUCCESS); 7532 } 7533 7534 /*@ 7535 MatGetBlockSize - Returns the matrix block size. 7536 7537 Not Collective 7538 7539 Input Parameter: 7540 . mat - the matrix 7541 7542 Output Parameter: 7543 . bs - block size 7544 7545 Level: intermediate 7546 7547 Notes: 7548 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7549 7550 If the block size has not been set yet this routine returns 1. 7551 7552 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7553 @*/ 7554 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7555 { 7556 PetscFunctionBegin; 7557 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7558 PetscAssertPointer(bs, 2); 7559 *bs = mat->rmap->bs; 7560 PetscFunctionReturn(PETSC_SUCCESS); 7561 } 7562 7563 /*@ 7564 MatGetBlockSizes - Returns the matrix block row and column sizes. 7565 7566 Not Collective 7567 7568 Input Parameter: 7569 . mat - the matrix 7570 7571 Output Parameters: 7572 + rbs - row block size 7573 - cbs - column block size 7574 7575 Level: intermediate 7576 7577 Notes: 7578 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7579 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7580 7581 If a block size has not been set yet this routine returns 1. 7582 7583 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7584 @*/ 7585 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7586 { 7587 PetscFunctionBegin; 7588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7589 if (rbs) PetscAssertPointer(rbs, 2); 7590 if (cbs) PetscAssertPointer(cbs, 3); 7591 if (rbs) *rbs = mat->rmap->bs; 7592 if (cbs) *cbs = mat->cmap->bs; 7593 PetscFunctionReturn(PETSC_SUCCESS); 7594 } 7595 7596 /*@ 7597 MatSetBlockSize - Sets the matrix block size. 7598 7599 Logically Collective 7600 7601 Input Parameters: 7602 + mat - the matrix 7603 - bs - block size 7604 7605 Level: intermediate 7606 7607 Notes: 7608 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7609 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7610 7611 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7612 is compatible with the matrix local sizes. 7613 7614 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7615 @*/ 7616 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7617 { 7618 PetscFunctionBegin; 7619 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7620 PetscValidLogicalCollectiveInt(mat, bs, 2); 7621 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7622 PetscFunctionReturn(PETSC_SUCCESS); 7623 } 7624 7625 typedef struct { 7626 PetscInt n; 7627 IS *is; 7628 Mat *mat; 7629 PetscObjectState nonzerostate; 7630 Mat C; 7631 } EnvelopeData; 7632 7633 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7634 { 7635 EnvelopeData *edata = (EnvelopeData *)*ptr; 7636 7637 PetscFunctionBegin; 7638 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7639 PetscCall(PetscFree(edata->is)); 7640 PetscCall(PetscFree(edata)); 7641 PetscFunctionReturn(PETSC_SUCCESS); 7642 } 7643 7644 /*@ 7645 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7646 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7647 7648 Collective 7649 7650 Input Parameter: 7651 . mat - the matrix 7652 7653 Level: intermediate 7654 7655 Notes: 7656 There can be zeros within the blocks 7657 7658 The blocks can overlap between processes, including laying on more than two processes 7659 7660 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7661 @*/ 7662 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7663 { 7664 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7665 PetscInt *diag, *odiag, sc; 7666 VecScatter scatter; 7667 PetscScalar *seqv; 7668 const PetscScalar *parv; 7669 const PetscInt *ia, *ja; 7670 PetscBool set, flag, done; 7671 Mat AA = mat, A; 7672 MPI_Comm comm; 7673 PetscMPIInt rank, size, tag; 7674 MPI_Status status; 7675 PetscContainer container; 7676 EnvelopeData *edata; 7677 Vec seq, par; 7678 IS isglobal; 7679 7680 PetscFunctionBegin; 7681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7682 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7683 if (!set || !flag) { 7684 /* TODO: only needs nonzero structure of transpose */ 7685 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7686 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7687 } 7688 PetscCall(MatAIJGetLocalMat(AA, &A)); 7689 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7690 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7691 7692 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7693 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7694 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7695 PetscCallMPI(MPI_Comm_size(comm, &size)); 7696 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7697 7698 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7699 7700 if (rank > 0) { 7701 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7702 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7703 } 7704 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7705 for (i = 0; i < n; i++) { 7706 env = PetscMax(env, ja[ia[i + 1] - 1]); 7707 II = rstart + i; 7708 if (env == II) { 7709 starts[lblocks] = tbs; 7710 sizes[lblocks++] = 1 + II - tbs; 7711 tbs = 1 + II; 7712 } 7713 } 7714 if (rank < size - 1) { 7715 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7716 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7717 } 7718 7719 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7720 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7721 PetscCall(MatDestroy(&A)); 7722 7723 PetscCall(PetscNew(&edata)); 7724 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7725 edata->n = lblocks; 7726 /* create IS needed for extracting blocks from the original matrix */ 7727 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7728 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7729 7730 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7731 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7732 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7733 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7734 PetscCall(MatSetType(edata->C, MATAIJ)); 7735 7736 /* Communicate the start and end of each row, from each block to the correct rank */ 7737 /* TODO: Use PetscSF instead of VecScatter */ 7738 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7739 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7740 PetscCall(VecGetArrayWrite(seq, &seqv)); 7741 for (PetscInt i = 0; i < lblocks; i++) { 7742 for (PetscInt j = 0; j < sizes[i]; j++) { 7743 seqv[cnt] = starts[i]; 7744 seqv[cnt + 1] = starts[i] + sizes[i]; 7745 cnt += 2; 7746 } 7747 } 7748 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7749 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7750 sc -= cnt; 7751 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7752 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7753 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7754 PetscCall(ISDestroy(&isglobal)); 7755 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7756 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7757 PetscCall(VecScatterDestroy(&scatter)); 7758 PetscCall(VecDestroy(&seq)); 7759 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7760 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7761 PetscCall(VecGetArrayRead(par, &parv)); 7762 cnt = 0; 7763 PetscCall(MatGetSize(mat, NULL, &n)); 7764 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7765 PetscInt start, end, d = 0, od = 0; 7766 7767 start = (PetscInt)PetscRealPart(parv[cnt]); 7768 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7769 cnt += 2; 7770 7771 if (start < cstart) { 7772 od += cstart - start + n - cend; 7773 d += cend - cstart; 7774 } else if (start < cend) { 7775 od += n - cend; 7776 d += cend - start; 7777 } else od += n - start; 7778 if (end <= cstart) { 7779 od -= cstart - end + n - cend; 7780 d -= cend - cstart; 7781 } else if (end < cend) { 7782 od -= n - cend; 7783 d -= cend - end; 7784 } else od -= n - end; 7785 7786 odiag[i] = od; 7787 diag[i] = d; 7788 } 7789 PetscCall(VecRestoreArrayRead(par, &parv)); 7790 PetscCall(VecDestroy(&par)); 7791 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7792 PetscCall(PetscFree2(diag, odiag)); 7793 PetscCall(PetscFree2(sizes, starts)); 7794 7795 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7796 PetscCall(PetscContainerSetPointer(container, edata)); 7797 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7798 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7799 PetscCall(PetscObjectDereference((PetscObject)container)); 7800 PetscFunctionReturn(PETSC_SUCCESS); 7801 } 7802 7803 /*@ 7804 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7805 7806 Collective 7807 7808 Input Parameters: 7809 + A - the matrix 7810 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7811 7812 Output Parameter: 7813 . C - matrix with inverted block diagonal of `A` 7814 7815 Level: advanced 7816 7817 Note: 7818 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7819 7820 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7821 @*/ 7822 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7823 { 7824 PetscContainer container; 7825 EnvelopeData *edata; 7826 PetscObjectState nonzerostate; 7827 7828 PetscFunctionBegin; 7829 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7830 if (!container) { 7831 PetscCall(MatComputeVariableBlockEnvelope(A)); 7832 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7833 } 7834 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7835 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7836 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7837 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7838 7839 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7840 *C = edata->C; 7841 7842 for (PetscInt i = 0; i < edata->n; i++) { 7843 Mat D; 7844 PetscScalar *dvalues; 7845 7846 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7847 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7848 PetscCall(MatSeqDenseInvert(D)); 7849 PetscCall(MatDenseGetArray(D, &dvalues)); 7850 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7851 PetscCall(MatDestroy(&D)); 7852 } 7853 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7854 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7855 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7856 PetscFunctionReturn(PETSC_SUCCESS); 7857 } 7858 7859 /*@ 7860 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7861 7862 Not Collective 7863 7864 Input Parameters: 7865 + mat - the matrix 7866 . nblocks - the number of blocks on this process, each block can only exist on a single process 7867 - bsizes - the block sizes 7868 7869 Level: intermediate 7870 7871 Notes: 7872 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7873 7874 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. 7875 7876 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7877 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7878 @*/ 7879 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7880 { 7881 PetscInt ncnt = 0, nlocal; 7882 7883 PetscFunctionBegin; 7884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7885 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7886 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); 7887 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7888 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); 7889 PetscCall(PetscFree(mat->bsizes)); 7890 mat->nblocks = nblocks; 7891 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7892 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7893 PetscFunctionReturn(PETSC_SUCCESS); 7894 } 7895 7896 /*@C 7897 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7898 7899 Not Collective; No Fortran Support 7900 7901 Input Parameter: 7902 . mat - the matrix 7903 7904 Output Parameters: 7905 + nblocks - the number of blocks on this process 7906 - bsizes - the block sizes 7907 7908 Level: intermediate 7909 7910 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7911 @*/ 7912 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7913 { 7914 PetscFunctionBegin; 7915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7916 if (nblocks) *nblocks = mat->nblocks; 7917 if (bsizes) *bsizes = mat->bsizes; 7918 PetscFunctionReturn(PETSC_SUCCESS); 7919 } 7920 7921 /* 7922 MatSelectVariableBlockSizes - When creating a submatrix, pass on the variable block sizes 7923 7924 Not Collective 7925 7926 Input Parameter: 7927 + subA - the submatrix 7928 . A - the original matrix 7929 - isrow - The `IS` of selected rows for the submatrix 7930 7931 Level: developer 7932 7933 .seealso: [](ch_matrices), `Mat`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7934 */ 7935 static PetscErrorCode MatSelectVariableBlockSizes(Mat subA, Mat A, IS isrow) 7936 { 7937 const PetscInt *rows; 7938 PetscInt n, rStart, rEnd, Nb = 0; 7939 7940 PetscFunctionBegin; 7941 if (!A->bsizes) PetscFunctionReturn(PETSC_SUCCESS); 7942 // The IS contains global row numbers, we cannot preserve blocks if it contains off-process entries 7943 PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd)); 7944 PetscCall(ISGetIndices(isrow, &rows)); 7945 PetscCall(ISGetLocalSize(isrow, &n)); 7946 for (PetscInt i = 0; i < n; ++i) { 7947 if (rows[i] < rStart || rows[i] >= rEnd) { 7948 PetscCall(ISRestoreIndices(isrow, &rows)); 7949 PetscFunctionReturn(PETSC_SUCCESS); 7950 } 7951 } 7952 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7953 PetscBool occupied = PETSC_FALSE; 7954 7955 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7956 const PetscInt row = gr + br; 7957 7958 if (i == n) break; 7959 if (rows[i] == row) { 7960 occupied = PETSC_TRUE; 7961 ++i; 7962 } 7963 while (i < n && rows[i] < row) ++i; 7964 } 7965 gr += A->bsizes[b]; 7966 if (occupied) ++Nb; 7967 } 7968 subA->nblocks = Nb; 7969 PetscCall(PetscFree(subA->bsizes)); 7970 PetscCall(PetscMalloc1(subA->nblocks, &subA->bsizes)); 7971 PetscInt sb = 0; 7972 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7973 if (sb < subA->nblocks) subA->bsizes[sb] = 0; 7974 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7975 const PetscInt row = gr + br; 7976 7977 if (i == n) break; 7978 if (rows[i] == row) { 7979 ++subA->bsizes[sb]; 7980 ++i; 7981 } 7982 while (i < n && rows[i] < row) ++i; 7983 } 7984 gr += A->bsizes[b]; 7985 if (sb < subA->nblocks && subA->bsizes[sb]) ++sb; 7986 } 7987 PetscCheck(sb == subA->nblocks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of blocks %" PetscInt_FMT " != %" PetscInt_FMT, sb, subA->nblocks); 7988 PetscInt nlocal, ncnt = 0; 7989 PetscCall(MatGetLocalSize(subA, &nlocal, NULL)); 7990 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); 7991 for (PetscInt i = 0; i < subA->nblocks; i++) ncnt += subA->bsizes[i]; 7992 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); 7993 PetscCall(ISRestoreIndices(isrow, &rows)); 7994 PetscFunctionReturn(PETSC_SUCCESS); 7995 } 7996 7997 /*@ 7998 MatSetBlockSizes - Sets the matrix block row and column sizes. 7999 8000 Logically Collective 8001 8002 Input Parameters: 8003 + mat - the matrix 8004 . rbs - row block size 8005 - cbs - column block size 8006 8007 Level: intermediate 8008 8009 Notes: 8010 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 8011 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 8012 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 8013 8014 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 8015 are compatible with the matrix local sizes. 8016 8017 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 8018 8019 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 8020 @*/ 8021 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8022 { 8023 PetscFunctionBegin; 8024 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8025 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8026 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8027 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8028 if (mat->rmap->refcnt) { 8029 ISLocalToGlobalMapping l2g = NULL; 8030 PetscLayout nmap = NULL; 8031 8032 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8033 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8034 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8035 mat->rmap = nmap; 8036 mat->rmap->mapping = l2g; 8037 } 8038 if (mat->cmap->refcnt) { 8039 ISLocalToGlobalMapping l2g = NULL; 8040 PetscLayout nmap = NULL; 8041 8042 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8043 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8044 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8045 mat->cmap = nmap; 8046 mat->cmap->mapping = l2g; 8047 } 8048 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8049 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8050 PetscFunctionReturn(PETSC_SUCCESS); 8051 } 8052 8053 /*@ 8054 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8055 8056 Logically Collective 8057 8058 Input Parameters: 8059 + mat - the matrix 8060 . fromRow - matrix from which to copy row block size 8061 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8062 8063 Level: developer 8064 8065 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8066 @*/ 8067 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8068 { 8069 PetscFunctionBegin; 8070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8071 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8072 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8073 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8074 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8075 PetscFunctionReturn(PETSC_SUCCESS); 8076 } 8077 8078 /*@ 8079 MatResidual - Default routine to calculate the residual r = b - Ax 8080 8081 Collective 8082 8083 Input Parameters: 8084 + mat - the matrix 8085 . b - the right-hand-side 8086 - x - the approximate solution 8087 8088 Output Parameter: 8089 . r - location to store the residual 8090 8091 Level: developer 8092 8093 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8094 @*/ 8095 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8096 { 8097 PetscFunctionBegin; 8098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8099 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8100 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8101 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8102 PetscValidType(mat, 1); 8103 MatCheckPreallocated(mat, 1); 8104 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8105 if (!mat->ops->residual) { 8106 PetscCall(MatMult(mat, x, r)); 8107 PetscCall(VecAYPX(r, -1.0, b)); 8108 } else { 8109 PetscUseTypeMethod(mat, residual, b, x, r); 8110 } 8111 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8112 PetscFunctionReturn(PETSC_SUCCESS); 8113 } 8114 8115 /*@C 8116 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8117 8118 Collective 8119 8120 Input Parameters: 8121 + mat - the matrix 8122 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8123 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8124 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8125 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8126 always used. 8127 8128 Output Parameters: 8129 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8130 . 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 8131 . ja - the column indices, use `NULL` if not needed 8132 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8133 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8134 8135 Level: developer 8136 8137 Notes: 8138 You CANNOT change any of the ia[] or ja[] values. 8139 8140 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8141 8142 Fortran Notes: 8143 Use 8144 .vb 8145 PetscInt, pointer :: ia(:),ja(:) 8146 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8147 ! Access the ith and jth entries via ia(i) and ja(j) 8148 .ve 8149 8150 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8151 @*/ 8152 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8153 { 8154 PetscFunctionBegin; 8155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8156 PetscValidType(mat, 1); 8157 if (n) PetscAssertPointer(n, 5); 8158 if (ia) PetscAssertPointer(ia, 6); 8159 if (ja) PetscAssertPointer(ja, 7); 8160 if (done) PetscAssertPointer(done, 8); 8161 MatCheckPreallocated(mat, 1); 8162 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8163 else { 8164 if (done) *done = PETSC_TRUE; 8165 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8166 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8167 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8168 } 8169 PetscFunctionReturn(PETSC_SUCCESS); 8170 } 8171 8172 /*@C 8173 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8174 8175 Collective 8176 8177 Input Parameters: 8178 + mat - the matrix 8179 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8180 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8181 symmetrized 8182 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8183 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8184 always used. 8185 . n - number of columns in the (possibly compressed) matrix 8186 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8187 - ja - the row indices 8188 8189 Output Parameter: 8190 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8191 8192 Level: developer 8193 8194 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8195 @*/ 8196 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8197 { 8198 PetscFunctionBegin; 8199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8200 PetscValidType(mat, 1); 8201 PetscAssertPointer(n, 5); 8202 if (ia) PetscAssertPointer(ia, 6); 8203 if (ja) PetscAssertPointer(ja, 7); 8204 PetscAssertPointer(done, 8); 8205 MatCheckPreallocated(mat, 1); 8206 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8207 else { 8208 *done = PETSC_TRUE; 8209 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8210 } 8211 PetscFunctionReturn(PETSC_SUCCESS); 8212 } 8213 8214 /*@C 8215 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8216 8217 Collective 8218 8219 Input Parameters: 8220 + mat - the matrix 8221 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8222 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8223 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8224 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8225 always used. 8226 . n - size of (possibly compressed) matrix 8227 . ia - the row pointers 8228 - ja - the column indices 8229 8230 Output Parameter: 8231 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8232 8233 Level: developer 8234 8235 Note: 8236 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8237 us of the array after it has been restored. If you pass `NULL`, it will 8238 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8239 8240 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8241 @*/ 8242 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8243 { 8244 PetscFunctionBegin; 8245 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8246 PetscValidType(mat, 1); 8247 if (ia) PetscAssertPointer(ia, 6); 8248 if (ja) PetscAssertPointer(ja, 7); 8249 if (done) PetscAssertPointer(done, 8); 8250 MatCheckPreallocated(mat, 1); 8251 8252 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8253 else { 8254 if (done) *done = PETSC_TRUE; 8255 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8256 if (n) *n = 0; 8257 if (ia) *ia = NULL; 8258 if (ja) *ja = NULL; 8259 } 8260 PetscFunctionReturn(PETSC_SUCCESS); 8261 } 8262 8263 /*@C 8264 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8265 8266 Collective 8267 8268 Input Parameters: 8269 + mat - the matrix 8270 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8271 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8272 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8273 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8274 always used. 8275 8276 Output Parameters: 8277 + n - size of (possibly compressed) matrix 8278 . ia - the column pointers 8279 . ja - the row indices 8280 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8281 8282 Level: developer 8283 8284 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8285 @*/ 8286 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8287 { 8288 PetscFunctionBegin; 8289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8290 PetscValidType(mat, 1); 8291 if (ia) PetscAssertPointer(ia, 6); 8292 if (ja) PetscAssertPointer(ja, 7); 8293 PetscAssertPointer(done, 8); 8294 MatCheckPreallocated(mat, 1); 8295 8296 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8297 else { 8298 *done = PETSC_TRUE; 8299 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8300 if (n) *n = 0; 8301 if (ia) *ia = NULL; 8302 if (ja) *ja = NULL; 8303 } 8304 PetscFunctionReturn(PETSC_SUCCESS); 8305 } 8306 8307 /*@ 8308 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8309 `MatGetColumnIJ()`. 8310 8311 Collective 8312 8313 Input Parameters: 8314 + mat - the matrix 8315 . ncolors - maximum color value 8316 . n - number of entries in colorarray 8317 - colorarray - array indicating color for each column 8318 8319 Output Parameter: 8320 . iscoloring - coloring generated using colorarray information 8321 8322 Level: developer 8323 8324 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8325 @*/ 8326 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8327 { 8328 PetscFunctionBegin; 8329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8330 PetscValidType(mat, 1); 8331 PetscAssertPointer(colorarray, 4); 8332 PetscAssertPointer(iscoloring, 5); 8333 MatCheckPreallocated(mat, 1); 8334 8335 if (!mat->ops->coloringpatch) { 8336 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8337 } else { 8338 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8339 } 8340 PetscFunctionReturn(PETSC_SUCCESS); 8341 } 8342 8343 /*@ 8344 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8345 8346 Logically Collective 8347 8348 Input Parameter: 8349 . mat - the factored matrix to be reset 8350 8351 Level: developer 8352 8353 Notes: 8354 This routine should be used only with factored matrices formed by in-place 8355 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8356 format). This option can save memory, for example, when solving nonlinear 8357 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8358 ILU(0) preconditioner. 8359 8360 One can specify in-place ILU(0) factorization by calling 8361 .vb 8362 PCType(pc,PCILU); 8363 PCFactorSeUseInPlace(pc); 8364 .ve 8365 or by using the options -pc_type ilu -pc_factor_in_place 8366 8367 In-place factorization ILU(0) can also be used as a local 8368 solver for the blocks within the block Jacobi or additive Schwarz 8369 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8370 for details on setting local solver options. 8371 8372 Most users should employ the `KSP` interface for linear solvers 8373 instead of working directly with matrix algebra routines such as this. 8374 See, e.g., `KSPCreate()`. 8375 8376 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8377 @*/ 8378 PetscErrorCode MatSetUnfactored(Mat mat) 8379 { 8380 PetscFunctionBegin; 8381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8382 PetscValidType(mat, 1); 8383 MatCheckPreallocated(mat, 1); 8384 mat->factortype = MAT_FACTOR_NONE; 8385 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8386 PetscUseTypeMethod(mat, setunfactored); 8387 PetscFunctionReturn(PETSC_SUCCESS); 8388 } 8389 8390 /*@ 8391 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8392 as the original matrix. 8393 8394 Collective 8395 8396 Input Parameters: 8397 + mat - the original matrix 8398 . isrow - parallel `IS` containing the rows this processor should obtain 8399 . 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. 8400 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8401 8402 Output Parameter: 8403 . newmat - the new submatrix, of the same type as the original matrix 8404 8405 Level: advanced 8406 8407 Notes: 8408 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8409 8410 Some matrix types place restrictions on the row and column indices, such 8411 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; 8412 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8413 8414 The index sets may not have duplicate entries. 8415 8416 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8417 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8418 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8419 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8420 you are finished using it. 8421 8422 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8423 the input matrix. 8424 8425 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8426 8427 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8428 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8429 8430 Example usage: 8431 Consider the following 8x8 matrix with 34 non-zero values, that is 8432 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8433 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8434 as follows 8435 .vb 8436 1 2 0 | 0 3 0 | 0 4 8437 Proc0 0 5 6 | 7 0 0 | 8 0 8438 9 0 10 | 11 0 0 | 12 0 8439 ------------------------------------- 8440 13 0 14 | 15 16 17 | 0 0 8441 Proc1 0 18 0 | 19 20 21 | 0 0 8442 0 0 0 | 22 23 0 | 24 0 8443 ------------------------------------- 8444 Proc2 25 26 27 | 0 0 28 | 29 0 8445 30 0 0 | 31 32 33 | 0 34 8446 .ve 8447 8448 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8449 8450 .vb 8451 2 0 | 0 3 0 | 0 8452 Proc0 5 6 | 7 0 0 | 8 8453 ------------------------------- 8454 Proc1 18 0 | 19 20 21 | 0 8455 ------------------------------- 8456 Proc2 26 27 | 0 0 28 | 29 8457 0 0 | 31 32 33 | 0 8458 .ve 8459 8460 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8461 @*/ 8462 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8463 { 8464 PetscMPIInt size; 8465 Mat *local; 8466 IS iscoltmp; 8467 PetscBool flg; 8468 8469 PetscFunctionBegin; 8470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8471 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8472 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8473 PetscAssertPointer(newmat, 5); 8474 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8475 PetscValidType(mat, 1); 8476 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8477 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8478 8479 MatCheckPreallocated(mat, 1); 8480 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8481 8482 if (!iscol || isrow == iscol) { 8483 PetscBool stride; 8484 PetscMPIInt grabentirematrix = 0, grab; 8485 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8486 if (stride) { 8487 PetscInt first, step, n, rstart, rend; 8488 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8489 if (step == 1) { 8490 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8491 if (rstart == first) { 8492 PetscCall(ISGetLocalSize(isrow, &n)); 8493 if (n == rend - rstart) grabentirematrix = 1; 8494 } 8495 } 8496 } 8497 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8498 if (grab) { 8499 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8500 if (cll == MAT_INITIAL_MATRIX) { 8501 *newmat = mat; 8502 PetscCall(PetscObjectReference((PetscObject)mat)); 8503 } 8504 PetscFunctionReturn(PETSC_SUCCESS); 8505 } 8506 } 8507 8508 if (!iscol) { 8509 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8510 } else { 8511 iscoltmp = iscol; 8512 } 8513 8514 /* if original matrix is on just one processor then use submatrix generated */ 8515 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8516 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8517 goto setproperties; 8518 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8519 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8520 *newmat = *local; 8521 PetscCall(PetscFree(local)); 8522 goto setproperties; 8523 } else if (!mat->ops->createsubmatrix) { 8524 /* Create a new matrix type that implements the operation using the full matrix */ 8525 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8526 switch (cll) { 8527 case MAT_INITIAL_MATRIX: 8528 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8529 break; 8530 case MAT_REUSE_MATRIX: 8531 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8532 break; 8533 default: 8534 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8535 } 8536 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8537 goto setproperties; 8538 } 8539 8540 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8541 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8542 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8543 8544 setproperties: 8545 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8546 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8547 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8548 } 8549 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8550 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8551 if (!iscol || isrow == iscol) PetscCall(MatSelectVariableBlockSizes(*newmat, mat, isrow)); 8552 PetscFunctionReturn(PETSC_SUCCESS); 8553 } 8554 8555 /*@ 8556 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8557 8558 Not Collective 8559 8560 Input Parameters: 8561 + A - the matrix we wish to propagate options from 8562 - B - the matrix we wish to propagate options to 8563 8564 Level: beginner 8565 8566 Note: 8567 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8568 8569 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8570 @*/ 8571 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8572 { 8573 PetscFunctionBegin; 8574 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8575 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8576 B->symmetry_eternal = A->symmetry_eternal; 8577 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8578 B->symmetric = A->symmetric; 8579 B->structurally_symmetric = A->structurally_symmetric; 8580 B->spd = A->spd; 8581 B->hermitian = A->hermitian; 8582 PetscFunctionReturn(PETSC_SUCCESS); 8583 } 8584 8585 /*@ 8586 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8587 used during the assembly process to store values that belong to 8588 other processors. 8589 8590 Not Collective 8591 8592 Input Parameters: 8593 + mat - the matrix 8594 . size - the initial size of the stash. 8595 - bsize - the initial size of the block-stash(if used). 8596 8597 Options Database Keys: 8598 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8599 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8600 8601 Level: intermediate 8602 8603 Notes: 8604 The block-stash is used for values set with `MatSetValuesBlocked()` while 8605 the stash is used for values set with `MatSetValues()` 8606 8607 Run with the option -info and look for output of the form 8608 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8609 to determine the appropriate value, MM, to use for size and 8610 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8611 to determine the value, BMM to use for bsize 8612 8613 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8614 @*/ 8615 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8616 { 8617 PetscFunctionBegin; 8618 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8619 PetscValidType(mat, 1); 8620 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8621 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8622 PetscFunctionReturn(PETSC_SUCCESS); 8623 } 8624 8625 /*@ 8626 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8627 the matrix 8628 8629 Neighbor-wise Collective 8630 8631 Input Parameters: 8632 + A - the matrix 8633 . x - the vector to be multiplied by the interpolation operator 8634 - y - the vector to be added to the result 8635 8636 Output Parameter: 8637 . w - the resulting vector 8638 8639 Level: intermediate 8640 8641 Notes: 8642 `w` may be the same vector as `y`. 8643 8644 This allows one to use either the restriction or interpolation (its transpose) 8645 matrix to do the interpolation 8646 8647 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8648 @*/ 8649 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8650 { 8651 PetscInt M, N, Ny; 8652 8653 PetscFunctionBegin; 8654 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8655 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8656 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8657 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8658 PetscCall(MatGetSize(A, &M, &N)); 8659 PetscCall(VecGetSize(y, &Ny)); 8660 if (M == Ny) { 8661 PetscCall(MatMultAdd(A, x, y, w)); 8662 } else { 8663 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8664 } 8665 PetscFunctionReturn(PETSC_SUCCESS); 8666 } 8667 8668 /*@ 8669 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8670 the matrix 8671 8672 Neighbor-wise Collective 8673 8674 Input Parameters: 8675 + A - the matrix 8676 - x - the vector to be interpolated 8677 8678 Output Parameter: 8679 . y - the resulting vector 8680 8681 Level: intermediate 8682 8683 Note: 8684 This allows one to use either the restriction or interpolation (its transpose) 8685 matrix to do the interpolation 8686 8687 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8688 @*/ 8689 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8690 { 8691 PetscInt M, N, Ny; 8692 8693 PetscFunctionBegin; 8694 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8695 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8696 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8697 PetscCall(MatGetSize(A, &M, &N)); 8698 PetscCall(VecGetSize(y, &Ny)); 8699 if (M == Ny) { 8700 PetscCall(MatMult(A, x, y)); 8701 } else { 8702 PetscCall(MatMultTranspose(A, x, y)); 8703 } 8704 PetscFunctionReturn(PETSC_SUCCESS); 8705 } 8706 8707 /*@ 8708 MatRestrict - $y = A*x$ or $A^T*x$ 8709 8710 Neighbor-wise Collective 8711 8712 Input Parameters: 8713 + A - the matrix 8714 - x - the vector to be restricted 8715 8716 Output Parameter: 8717 . y - the resulting vector 8718 8719 Level: intermediate 8720 8721 Note: 8722 This allows one to use either the restriction or interpolation (its transpose) 8723 matrix to do the restriction 8724 8725 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8726 @*/ 8727 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8728 { 8729 PetscInt M, N, Nx; 8730 8731 PetscFunctionBegin; 8732 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8733 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8734 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8735 PetscCall(MatGetSize(A, &M, &N)); 8736 PetscCall(VecGetSize(x, &Nx)); 8737 if (M == Nx) { 8738 PetscCall(MatMultTranspose(A, x, y)); 8739 } else { 8740 PetscCall(MatMult(A, x, y)); 8741 } 8742 PetscFunctionReturn(PETSC_SUCCESS); 8743 } 8744 8745 /*@ 8746 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8747 8748 Neighbor-wise Collective 8749 8750 Input Parameters: 8751 + A - the matrix 8752 . x - the input dense matrix to be multiplied 8753 - w - the input dense matrix to be added to the result 8754 8755 Output Parameter: 8756 . y - the output dense matrix 8757 8758 Level: intermediate 8759 8760 Note: 8761 This allows one to use either the restriction or interpolation (its transpose) 8762 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8763 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8764 8765 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8766 @*/ 8767 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8768 { 8769 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8770 PetscBool trans = PETSC_TRUE; 8771 MatReuse reuse = MAT_INITIAL_MATRIX; 8772 8773 PetscFunctionBegin; 8774 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8775 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8776 PetscValidType(x, 2); 8777 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8778 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8779 PetscCall(MatGetSize(A, &M, &N)); 8780 PetscCall(MatGetSize(x, &Mx, &Nx)); 8781 if (N == Mx) trans = PETSC_FALSE; 8782 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); 8783 Mo = trans ? N : M; 8784 if (*y) { 8785 PetscCall(MatGetSize(*y, &My, &Ny)); 8786 if (Mo == My && Nx == Ny) { 8787 reuse = MAT_REUSE_MATRIX; 8788 } else { 8789 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); 8790 PetscCall(MatDestroy(y)); 8791 } 8792 } 8793 8794 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8795 PetscBool flg; 8796 8797 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8798 if (w) { 8799 PetscInt My, Ny, Mw, Nw; 8800 8801 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8802 PetscCall(MatGetSize(*y, &My, &Ny)); 8803 PetscCall(MatGetSize(w, &Mw, &Nw)); 8804 if (!flg || My != Mw || Ny != Nw) w = NULL; 8805 } 8806 if (!w) { 8807 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8808 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8809 PetscCall(PetscObjectDereference((PetscObject)w)); 8810 } else { 8811 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8812 } 8813 } 8814 if (!trans) { 8815 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8816 } else { 8817 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8818 } 8819 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8820 PetscFunctionReturn(PETSC_SUCCESS); 8821 } 8822 8823 /*@ 8824 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8825 8826 Neighbor-wise Collective 8827 8828 Input Parameters: 8829 + A - the matrix 8830 - x - the input dense matrix 8831 8832 Output Parameter: 8833 . y - the output dense matrix 8834 8835 Level: intermediate 8836 8837 Note: 8838 This allows one to use either the restriction or interpolation (its transpose) 8839 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8840 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8841 8842 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8843 @*/ 8844 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8845 { 8846 PetscFunctionBegin; 8847 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8848 PetscFunctionReturn(PETSC_SUCCESS); 8849 } 8850 8851 /*@ 8852 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8853 8854 Neighbor-wise Collective 8855 8856 Input Parameters: 8857 + A - the matrix 8858 - x - the input dense matrix 8859 8860 Output Parameter: 8861 . y - the output dense matrix 8862 8863 Level: intermediate 8864 8865 Note: 8866 This allows one to use either the restriction or interpolation (its transpose) 8867 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8868 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8869 8870 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8871 @*/ 8872 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8873 { 8874 PetscFunctionBegin; 8875 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8876 PetscFunctionReturn(PETSC_SUCCESS); 8877 } 8878 8879 /*@ 8880 MatGetNullSpace - retrieves the null space of a matrix. 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + mat - the matrix 8886 - nullsp - the null space object 8887 8888 Level: developer 8889 8890 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8891 @*/ 8892 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8893 { 8894 PetscFunctionBegin; 8895 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8896 PetscAssertPointer(nullsp, 2); 8897 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8898 PetscFunctionReturn(PETSC_SUCCESS); 8899 } 8900 8901 /*@C 8902 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8903 8904 Logically Collective 8905 8906 Input Parameters: 8907 + n - the number of matrices 8908 - mat - the array of matrices 8909 8910 Output Parameters: 8911 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8912 8913 Level: developer 8914 8915 Note: 8916 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8917 8918 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8919 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8920 @*/ 8921 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8922 { 8923 PetscFunctionBegin; 8924 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8925 PetscAssertPointer(mat, 2); 8926 PetscAssertPointer(nullsp, 3); 8927 8928 PetscCall(PetscCalloc1(3 * n, nullsp)); 8929 for (PetscInt i = 0; i < n; i++) { 8930 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8931 (*nullsp)[i] = mat[i]->nullsp; 8932 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8933 (*nullsp)[n + i] = mat[i]->nearnullsp; 8934 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8935 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8936 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8937 } 8938 PetscFunctionReturn(PETSC_SUCCESS); 8939 } 8940 8941 /*@C 8942 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8943 8944 Logically Collective 8945 8946 Input Parameters: 8947 + n - the number of matrices 8948 . mat - the array of matrices 8949 - nullsp - an array of null spaces 8950 8951 Level: developer 8952 8953 Note: 8954 Call `MatGetNullSpaces()` to create `nullsp` 8955 8956 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8957 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8958 @*/ 8959 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8960 { 8961 PetscFunctionBegin; 8962 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8963 PetscAssertPointer(mat, 2); 8964 PetscAssertPointer(nullsp, 3); 8965 PetscAssertPointer(*nullsp, 3); 8966 8967 for (PetscInt i = 0; i < n; i++) { 8968 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8969 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8970 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8971 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8972 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8973 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8974 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8975 } 8976 PetscCall(PetscFree(*nullsp)); 8977 PetscFunctionReturn(PETSC_SUCCESS); 8978 } 8979 8980 /*@ 8981 MatSetNullSpace - attaches a null space to a matrix. 8982 8983 Logically Collective 8984 8985 Input Parameters: 8986 + mat - the matrix 8987 - nullsp - the null space object 8988 8989 Level: advanced 8990 8991 Notes: 8992 This null space is used by the `KSP` linear solvers to solve singular systems. 8993 8994 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` 8995 8996 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 8997 to zero but the linear system will still be solved in a least squares sense. 8998 8999 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9000 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)$. 9001 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 9002 $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 9003 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)$. 9004 This $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9005 9006 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called 9007 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9008 routine also automatically calls `MatSetTransposeNullSpace()`. 9009 9010 The user should call `MatNullSpaceDestroy()`. 9011 9012 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9013 `KSPSetPCSide()` 9014 @*/ 9015 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9016 { 9017 PetscFunctionBegin; 9018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9019 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9020 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9021 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9022 mat->nullsp = nullsp; 9023 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9024 PetscFunctionReturn(PETSC_SUCCESS); 9025 } 9026 9027 /*@ 9028 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9029 9030 Logically Collective 9031 9032 Input Parameters: 9033 + mat - the matrix 9034 - nullsp - the null space object 9035 9036 Level: developer 9037 9038 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9039 @*/ 9040 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9041 { 9042 PetscFunctionBegin; 9043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9044 PetscValidType(mat, 1); 9045 PetscAssertPointer(nullsp, 2); 9046 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9047 PetscFunctionReturn(PETSC_SUCCESS); 9048 } 9049 9050 /*@ 9051 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9052 9053 Logically Collective 9054 9055 Input Parameters: 9056 + mat - the matrix 9057 - nullsp - the null space object 9058 9059 Level: advanced 9060 9061 Notes: 9062 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9063 9064 See `MatSetNullSpace()` 9065 9066 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9067 @*/ 9068 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9069 { 9070 PetscFunctionBegin; 9071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9072 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9073 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9074 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9075 mat->transnullsp = nullsp; 9076 PetscFunctionReturn(PETSC_SUCCESS); 9077 } 9078 9079 /*@ 9080 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9081 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9082 9083 Logically Collective 9084 9085 Input Parameters: 9086 + mat - the matrix 9087 - nullsp - the null space object 9088 9089 Level: advanced 9090 9091 Notes: 9092 Overwrites any previous near null space that may have been attached 9093 9094 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9095 9096 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9097 @*/ 9098 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9099 { 9100 PetscFunctionBegin; 9101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9102 PetscValidType(mat, 1); 9103 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9104 MatCheckPreallocated(mat, 1); 9105 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9106 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9107 mat->nearnullsp = nullsp; 9108 PetscFunctionReturn(PETSC_SUCCESS); 9109 } 9110 9111 /*@ 9112 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9113 9114 Not Collective 9115 9116 Input Parameter: 9117 . mat - the matrix 9118 9119 Output Parameter: 9120 . nullsp - the null space object, `NULL` if not set 9121 9122 Level: advanced 9123 9124 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9125 @*/ 9126 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9127 { 9128 PetscFunctionBegin; 9129 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9130 PetscValidType(mat, 1); 9131 PetscAssertPointer(nullsp, 2); 9132 MatCheckPreallocated(mat, 1); 9133 *nullsp = mat->nearnullsp; 9134 PetscFunctionReturn(PETSC_SUCCESS); 9135 } 9136 9137 /*@ 9138 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9139 9140 Collective 9141 9142 Input Parameters: 9143 + mat - the matrix 9144 . row - row/column permutation 9145 - info - information on desired factorization process 9146 9147 Level: developer 9148 9149 Notes: 9150 Probably really in-place only when level of fill is zero, otherwise allocates 9151 new space to store factored matrix and deletes previous memory. 9152 9153 Most users should employ the `KSP` interface for linear solvers 9154 instead of working directly with matrix algebra routines such as this. 9155 See, e.g., `KSPCreate()`. 9156 9157 Fortran Note: 9158 A valid (non-null) `info` argument must be provided 9159 9160 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9161 @*/ 9162 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9163 { 9164 PetscFunctionBegin; 9165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9166 PetscValidType(mat, 1); 9167 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9168 PetscAssertPointer(info, 3); 9169 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9170 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9171 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9172 MatCheckPreallocated(mat, 1); 9173 PetscUseTypeMethod(mat, iccfactor, row, info); 9174 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9175 PetscFunctionReturn(PETSC_SUCCESS); 9176 } 9177 9178 /*@ 9179 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9180 ghosted ones. 9181 9182 Not Collective 9183 9184 Input Parameters: 9185 + mat - the matrix 9186 - diag - the diagonal values, including ghost ones 9187 9188 Level: developer 9189 9190 Notes: 9191 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9192 9193 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9194 9195 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9196 @*/ 9197 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9198 { 9199 PetscMPIInt size; 9200 9201 PetscFunctionBegin; 9202 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9203 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9204 PetscValidType(mat, 1); 9205 9206 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9207 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9208 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9209 if (size == 1) { 9210 PetscInt n, m; 9211 PetscCall(VecGetSize(diag, &n)); 9212 PetscCall(MatGetSize(mat, NULL, &m)); 9213 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9214 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9215 } else { 9216 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9217 } 9218 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9219 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9220 PetscFunctionReturn(PETSC_SUCCESS); 9221 } 9222 9223 /*@ 9224 MatGetInertia - Gets the inertia from a factored matrix 9225 9226 Collective 9227 9228 Input Parameter: 9229 . mat - the matrix 9230 9231 Output Parameters: 9232 + nneg - number of negative eigenvalues 9233 . nzero - number of zero eigenvalues 9234 - npos - number of positive eigenvalues 9235 9236 Level: advanced 9237 9238 Note: 9239 Matrix must have been factored by `MatCholeskyFactor()` 9240 9241 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9242 @*/ 9243 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9244 { 9245 PetscFunctionBegin; 9246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9247 PetscValidType(mat, 1); 9248 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9249 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9250 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9251 PetscFunctionReturn(PETSC_SUCCESS); 9252 } 9253 9254 /*@C 9255 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9256 9257 Neighbor-wise Collective 9258 9259 Input Parameters: 9260 + mat - the factored matrix obtained with `MatGetFactor()` 9261 - b - the right-hand-side vectors 9262 9263 Output Parameter: 9264 . x - the result vectors 9265 9266 Level: developer 9267 9268 Note: 9269 The vectors `b` and `x` cannot be the same. I.e., one cannot 9270 call `MatSolves`(A,x,x). 9271 9272 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9273 @*/ 9274 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9275 { 9276 PetscFunctionBegin; 9277 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9278 PetscValidType(mat, 1); 9279 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9280 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9281 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9282 9283 MatCheckPreallocated(mat, 1); 9284 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9285 PetscUseTypeMethod(mat, solves, b, x); 9286 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9287 PetscFunctionReturn(PETSC_SUCCESS); 9288 } 9289 9290 /*@ 9291 MatIsSymmetric - Test whether a matrix is symmetric 9292 9293 Collective 9294 9295 Input Parameters: 9296 + A - the matrix to test 9297 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9298 9299 Output Parameter: 9300 . flg - the result 9301 9302 Level: intermediate 9303 9304 Notes: 9305 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9306 9307 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9308 9309 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9310 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9311 9312 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9313 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9314 @*/ 9315 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9316 { 9317 PetscFunctionBegin; 9318 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9319 PetscAssertPointer(flg, 3); 9320 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9321 else { 9322 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9323 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9324 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9325 } 9326 PetscFunctionReturn(PETSC_SUCCESS); 9327 } 9328 9329 /*@ 9330 MatIsHermitian - Test whether a matrix is Hermitian 9331 9332 Collective 9333 9334 Input Parameters: 9335 + A - the matrix to test 9336 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9337 9338 Output Parameter: 9339 . flg - the result 9340 9341 Level: intermediate 9342 9343 Notes: 9344 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9345 9346 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9347 9348 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9349 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9350 9351 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9352 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9353 @*/ 9354 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9355 { 9356 PetscFunctionBegin; 9357 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9358 PetscAssertPointer(flg, 3); 9359 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9360 else { 9361 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9362 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9363 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9364 } 9365 PetscFunctionReturn(PETSC_SUCCESS); 9366 } 9367 9368 /*@ 9369 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9370 9371 Not Collective 9372 9373 Input Parameter: 9374 . A - the matrix to check 9375 9376 Output Parameters: 9377 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9378 - flg - the result (only valid if set is `PETSC_TRUE`) 9379 9380 Level: advanced 9381 9382 Notes: 9383 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9384 if you want it explicitly checked 9385 9386 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9387 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9388 9389 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9390 @*/ 9391 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9392 { 9393 PetscFunctionBegin; 9394 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9395 PetscAssertPointer(set, 2); 9396 PetscAssertPointer(flg, 3); 9397 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9398 *set = PETSC_TRUE; 9399 *flg = PetscBool3ToBool(A->symmetric); 9400 } else { 9401 *set = PETSC_FALSE; 9402 } 9403 PetscFunctionReturn(PETSC_SUCCESS); 9404 } 9405 9406 /*@ 9407 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9408 9409 Not Collective 9410 9411 Input Parameter: 9412 . A - the matrix to check 9413 9414 Output Parameters: 9415 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9416 - flg - the result (only valid if set is `PETSC_TRUE`) 9417 9418 Level: advanced 9419 9420 Notes: 9421 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9422 9423 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9424 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9425 9426 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9427 @*/ 9428 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9429 { 9430 PetscFunctionBegin; 9431 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9432 PetscAssertPointer(set, 2); 9433 PetscAssertPointer(flg, 3); 9434 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9435 *set = PETSC_TRUE; 9436 *flg = PetscBool3ToBool(A->spd); 9437 } else { 9438 *set = PETSC_FALSE; 9439 } 9440 PetscFunctionReturn(PETSC_SUCCESS); 9441 } 9442 9443 /*@ 9444 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9445 9446 Not Collective 9447 9448 Input Parameter: 9449 . A - the matrix to check 9450 9451 Output Parameters: 9452 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9453 - flg - the result (only valid if set is `PETSC_TRUE`) 9454 9455 Level: advanced 9456 9457 Notes: 9458 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9459 if you want it explicitly checked 9460 9461 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9462 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9463 9464 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9465 @*/ 9466 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9467 { 9468 PetscFunctionBegin; 9469 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9470 PetscAssertPointer(set, 2); 9471 PetscAssertPointer(flg, 3); 9472 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9473 *set = PETSC_TRUE; 9474 *flg = PetscBool3ToBool(A->hermitian); 9475 } else { 9476 *set = PETSC_FALSE; 9477 } 9478 PetscFunctionReturn(PETSC_SUCCESS); 9479 } 9480 9481 /*@ 9482 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9483 9484 Collective 9485 9486 Input Parameter: 9487 . A - the matrix to test 9488 9489 Output Parameter: 9490 . flg - the result 9491 9492 Level: intermediate 9493 9494 Notes: 9495 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9496 9497 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 9498 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9499 9500 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9501 @*/ 9502 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9503 { 9504 PetscFunctionBegin; 9505 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9506 PetscAssertPointer(flg, 2); 9507 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9508 *flg = PetscBool3ToBool(A->structurally_symmetric); 9509 } else { 9510 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9511 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9512 } 9513 PetscFunctionReturn(PETSC_SUCCESS); 9514 } 9515 9516 /*@ 9517 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9518 9519 Not Collective 9520 9521 Input Parameter: 9522 . A - the matrix to check 9523 9524 Output Parameters: 9525 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9526 - flg - the result (only valid if set is PETSC_TRUE) 9527 9528 Level: advanced 9529 9530 Notes: 9531 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 9532 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9533 9534 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9535 9536 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9537 @*/ 9538 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9539 { 9540 PetscFunctionBegin; 9541 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9542 PetscAssertPointer(set, 2); 9543 PetscAssertPointer(flg, 3); 9544 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9545 *set = PETSC_TRUE; 9546 *flg = PetscBool3ToBool(A->structurally_symmetric); 9547 } else { 9548 *set = PETSC_FALSE; 9549 } 9550 PetscFunctionReturn(PETSC_SUCCESS); 9551 } 9552 9553 /*@ 9554 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9555 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9556 9557 Not Collective 9558 9559 Input Parameter: 9560 . mat - the matrix 9561 9562 Output Parameters: 9563 + nstash - the size of the stash 9564 . reallocs - the number of additional mallocs incurred. 9565 . bnstash - the size of the block stash 9566 - breallocs - the number of additional mallocs incurred.in the block stash 9567 9568 Level: advanced 9569 9570 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9571 @*/ 9572 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9573 { 9574 PetscFunctionBegin; 9575 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9576 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9577 PetscFunctionReturn(PETSC_SUCCESS); 9578 } 9579 9580 /*@ 9581 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9582 parallel layout, `PetscLayout` for rows and columns 9583 9584 Collective 9585 9586 Input Parameter: 9587 . mat - the matrix 9588 9589 Output Parameters: 9590 + right - (optional) vector that the matrix can be multiplied against 9591 - left - (optional) vector that the matrix vector product can be stored in 9592 9593 Level: advanced 9594 9595 Notes: 9596 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()`. 9597 9598 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9599 9600 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9601 @*/ 9602 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9603 { 9604 PetscFunctionBegin; 9605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9606 PetscValidType(mat, 1); 9607 if (mat->ops->getvecs) { 9608 PetscUseTypeMethod(mat, getvecs, right, left); 9609 } else { 9610 if (right) { 9611 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9612 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9613 PetscCall(VecSetType(*right, mat->defaultvectype)); 9614 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9615 if (mat->boundtocpu && mat->bindingpropagates) { 9616 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9617 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9618 } 9619 #endif 9620 } 9621 if (left) { 9622 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9623 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9624 PetscCall(VecSetType(*left, mat->defaultvectype)); 9625 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9626 if (mat->boundtocpu && mat->bindingpropagates) { 9627 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9628 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9629 } 9630 #endif 9631 } 9632 } 9633 PetscFunctionReturn(PETSC_SUCCESS); 9634 } 9635 9636 /*@ 9637 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9638 with default values. 9639 9640 Not Collective 9641 9642 Input Parameter: 9643 . info - the `MatFactorInfo` data structure 9644 9645 Level: developer 9646 9647 Notes: 9648 The solvers are generally used through the `KSP` and `PC` objects, for example 9649 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9650 9651 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9652 9653 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9654 @*/ 9655 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9656 { 9657 PetscFunctionBegin; 9658 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9659 PetscFunctionReturn(PETSC_SUCCESS); 9660 } 9661 9662 /*@ 9663 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9664 9665 Collective 9666 9667 Input Parameters: 9668 + mat - the factored matrix 9669 - is - the index set defining the Schur indices (0-based) 9670 9671 Level: advanced 9672 9673 Notes: 9674 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9675 9676 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9677 9678 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9679 9680 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9681 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9682 @*/ 9683 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9684 { 9685 PetscErrorCode (*f)(Mat, IS); 9686 9687 PetscFunctionBegin; 9688 PetscValidType(mat, 1); 9689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9690 PetscValidType(is, 2); 9691 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9692 PetscCheckSameComm(mat, 1, is, 2); 9693 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9694 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9695 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9696 PetscCall(MatDestroy(&mat->schur)); 9697 PetscCall((*f)(mat, is)); 9698 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9699 PetscFunctionReturn(PETSC_SUCCESS); 9700 } 9701 9702 /*@ 9703 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9704 9705 Logically Collective 9706 9707 Input Parameters: 9708 + F - the factored matrix obtained by calling `MatGetFactor()` 9709 . S - location where to return the Schur complement, can be `NULL` 9710 - status - the status of the Schur complement matrix, can be `NULL` 9711 9712 Level: advanced 9713 9714 Notes: 9715 You must call `MatFactorSetSchurIS()` before calling this routine. 9716 9717 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9718 9719 The routine provides a copy of the Schur matrix stored within the solver data structures. 9720 The caller must destroy the object when it is no longer needed. 9721 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9722 9723 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) 9724 9725 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9726 9727 Developer Note: 9728 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9729 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9730 9731 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9732 @*/ 9733 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9734 { 9735 PetscFunctionBegin; 9736 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9737 if (S) PetscAssertPointer(S, 2); 9738 if (status) PetscAssertPointer(status, 3); 9739 if (S) { 9740 PetscErrorCode (*f)(Mat, Mat *); 9741 9742 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9743 if (f) { 9744 PetscCall((*f)(F, S)); 9745 } else { 9746 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9747 } 9748 } 9749 if (status) *status = F->schur_status; 9750 PetscFunctionReturn(PETSC_SUCCESS); 9751 } 9752 9753 /*@ 9754 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9755 9756 Logically Collective 9757 9758 Input Parameters: 9759 + F - the factored matrix obtained by calling `MatGetFactor()` 9760 . S - location where to return the Schur complement, can be `NULL` 9761 - status - the status of the Schur complement matrix, can be `NULL` 9762 9763 Level: advanced 9764 9765 Notes: 9766 You must call `MatFactorSetSchurIS()` before calling this routine. 9767 9768 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9769 9770 The routine returns a the Schur Complement stored within the data structures of the solver. 9771 9772 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9773 9774 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9775 9776 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9777 9778 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9779 9780 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9781 @*/ 9782 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9783 { 9784 PetscFunctionBegin; 9785 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9786 if (S) { 9787 PetscAssertPointer(S, 2); 9788 *S = F->schur; 9789 } 9790 if (status) { 9791 PetscAssertPointer(status, 3); 9792 *status = F->schur_status; 9793 } 9794 PetscFunctionReturn(PETSC_SUCCESS); 9795 } 9796 9797 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9798 { 9799 Mat S = F->schur; 9800 9801 PetscFunctionBegin; 9802 switch (F->schur_status) { 9803 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9804 case MAT_FACTOR_SCHUR_INVERTED: 9805 if (S) { 9806 S->ops->solve = NULL; 9807 S->ops->matsolve = NULL; 9808 S->ops->solvetranspose = NULL; 9809 S->ops->matsolvetranspose = NULL; 9810 S->ops->solveadd = NULL; 9811 S->ops->solvetransposeadd = NULL; 9812 S->factortype = MAT_FACTOR_NONE; 9813 PetscCall(PetscFree(S->solvertype)); 9814 } 9815 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9816 break; 9817 default: 9818 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9819 } 9820 PetscFunctionReturn(PETSC_SUCCESS); 9821 } 9822 9823 /*@ 9824 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9825 9826 Logically Collective 9827 9828 Input Parameters: 9829 + F - the factored matrix obtained by calling `MatGetFactor()` 9830 . S - location where the Schur complement is stored 9831 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9832 9833 Level: advanced 9834 9835 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9836 @*/ 9837 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9838 { 9839 PetscFunctionBegin; 9840 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9841 if (S) { 9842 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9843 *S = NULL; 9844 } 9845 F->schur_status = status; 9846 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9847 PetscFunctionReturn(PETSC_SUCCESS); 9848 } 9849 9850 /*@ 9851 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9852 9853 Logically Collective 9854 9855 Input Parameters: 9856 + F - the factored matrix obtained by calling `MatGetFactor()` 9857 . rhs - location where the right-hand side of the Schur complement system is stored 9858 - sol - location where the solution of the Schur complement system has to be returned 9859 9860 Level: advanced 9861 9862 Notes: 9863 The sizes of the vectors should match the size of the Schur complement 9864 9865 Must be called after `MatFactorSetSchurIS()` 9866 9867 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9868 @*/ 9869 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9870 { 9871 PetscFunctionBegin; 9872 PetscValidType(F, 1); 9873 PetscValidType(rhs, 2); 9874 PetscValidType(sol, 3); 9875 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9876 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9877 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9878 PetscCheckSameComm(F, 1, rhs, 2); 9879 PetscCheckSameComm(F, 1, sol, 3); 9880 PetscCall(MatFactorFactorizeSchurComplement(F)); 9881 switch (F->schur_status) { 9882 case MAT_FACTOR_SCHUR_FACTORED: 9883 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9884 break; 9885 case MAT_FACTOR_SCHUR_INVERTED: 9886 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9887 break; 9888 default: 9889 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9890 } 9891 PetscFunctionReturn(PETSC_SUCCESS); 9892 } 9893 9894 /*@ 9895 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9896 9897 Logically Collective 9898 9899 Input Parameters: 9900 + F - the factored matrix obtained by calling `MatGetFactor()` 9901 . rhs - location where the right-hand side of the Schur complement system is stored 9902 - sol - location where the solution of the Schur complement system has to be returned 9903 9904 Level: advanced 9905 9906 Notes: 9907 The sizes of the vectors should match the size of the Schur complement 9908 9909 Must be called after `MatFactorSetSchurIS()` 9910 9911 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9912 @*/ 9913 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9914 { 9915 PetscFunctionBegin; 9916 PetscValidType(F, 1); 9917 PetscValidType(rhs, 2); 9918 PetscValidType(sol, 3); 9919 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9920 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9921 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9922 PetscCheckSameComm(F, 1, rhs, 2); 9923 PetscCheckSameComm(F, 1, sol, 3); 9924 PetscCall(MatFactorFactorizeSchurComplement(F)); 9925 switch (F->schur_status) { 9926 case MAT_FACTOR_SCHUR_FACTORED: 9927 PetscCall(MatSolve(F->schur, rhs, sol)); 9928 break; 9929 case MAT_FACTOR_SCHUR_INVERTED: 9930 PetscCall(MatMult(F->schur, rhs, sol)); 9931 break; 9932 default: 9933 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9934 } 9935 PetscFunctionReturn(PETSC_SUCCESS); 9936 } 9937 9938 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9939 #if PetscDefined(HAVE_CUDA) 9940 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9941 #endif 9942 9943 /* Schur status updated in the interface */ 9944 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9945 { 9946 Mat S = F->schur; 9947 9948 PetscFunctionBegin; 9949 if (S) { 9950 PetscMPIInt size; 9951 PetscBool isdense, isdensecuda; 9952 9953 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9954 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9955 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9956 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9957 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9958 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9959 if (isdense) { 9960 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9961 } else if (isdensecuda) { 9962 #if defined(PETSC_HAVE_CUDA) 9963 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9964 #endif 9965 } 9966 // HIP?????????????? 9967 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9968 } 9969 PetscFunctionReturn(PETSC_SUCCESS); 9970 } 9971 9972 /*@ 9973 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9974 9975 Logically Collective 9976 9977 Input Parameter: 9978 . F - the factored matrix obtained by calling `MatGetFactor()` 9979 9980 Level: advanced 9981 9982 Notes: 9983 Must be called after `MatFactorSetSchurIS()`. 9984 9985 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9986 9987 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9988 @*/ 9989 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9990 { 9991 PetscFunctionBegin; 9992 PetscValidType(F, 1); 9993 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9994 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9995 PetscCall(MatFactorFactorizeSchurComplement(F)); 9996 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9997 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9998 PetscFunctionReturn(PETSC_SUCCESS); 9999 } 10000 10001 /*@ 10002 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10003 10004 Logically Collective 10005 10006 Input Parameter: 10007 . F - the factored matrix obtained by calling `MatGetFactor()` 10008 10009 Level: advanced 10010 10011 Note: 10012 Must be called after `MatFactorSetSchurIS()` 10013 10014 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10015 @*/ 10016 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10017 { 10018 MatFactorInfo info; 10019 10020 PetscFunctionBegin; 10021 PetscValidType(F, 1); 10022 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10023 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10024 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10025 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10026 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10027 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10028 } else { 10029 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10030 } 10031 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10032 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10033 PetscFunctionReturn(PETSC_SUCCESS); 10034 } 10035 10036 /*@ 10037 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10038 10039 Neighbor-wise Collective 10040 10041 Input Parameters: 10042 + A - the matrix 10043 . P - the projection matrix 10044 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10045 - 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 10046 if the result is a dense matrix this is irrelevant 10047 10048 Output Parameter: 10049 . C - the product matrix 10050 10051 Level: intermediate 10052 10053 Notes: 10054 C will be created and must be destroyed by the user with `MatDestroy()`. 10055 10056 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10057 10058 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10059 10060 Developer Note: 10061 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10062 10063 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10064 @*/ 10065 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10066 { 10067 PetscFunctionBegin; 10068 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10069 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10070 10071 if (scall == MAT_INITIAL_MATRIX) { 10072 PetscCall(MatProductCreate(A, P, NULL, C)); 10073 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10074 PetscCall(MatProductSetAlgorithm(*C, "default")); 10075 PetscCall(MatProductSetFill(*C, fill)); 10076 10077 (*C)->product->api_user = PETSC_TRUE; 10078 PetscCall(MatProductSetFromOptions(*C)); 10079 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); 10080 PetscCall(MatProductSymbolic(*C)); 10081 } else { /* scall == MAT_REUSE_MATRIX */ 10082 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10083 } 10084 10085 PetscCall(MatProductNumeric(*C)); 10086 (*C)->symmetric = A->symmetric; 10087 (*C)->spd = A->spd; 10088 PetscFunctionReturn(PETSC_SUCCESS); 10089 } 10090 10091 /*@ 10092 MatRARt - Creates the matrix product $C = R * A * R^T$ 10093 10094 Neighbor-wise Collective 10095 10096 Input Parameters: 10097 + A - the matrix 10098 . R - the projection matrix 10099 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10100 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10101 if the result is a dense matrix this is irrelevant 10102 10103 Output Parameter: 10104 . C - the product matrix 10105 10106 Level: intermediate 10107 10108 Notes: 10109 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10110 10111 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10112 10113 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10114 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10115 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10116 We recommend using `MatPtAP()` when possible. 10117 10118 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10119 10120 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10121 @*/ 10122 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10123 { 10124 PetscFunctionBegin; 10125 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10126 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10127 10128 if (scall == MAT_INITIAL_MATRIX) { 10129 PetscCall(MatProductCreate(A, R, NULL, C)); 10130 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10131 PetscCall(MatProductSetAlgorithm(*C, "default")); 10132 PetscCall(MatProductSetFill(*C, fill)); 10133 10134 (*C)->product->api_user = PETSC_TRUE; 10135 PetscCall(MatProductSetFromOptions(*C)); 10136 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); 10137 PetscCall(MatProductSymbolic(*C)); 10138 } else { /* scall == MAT_REUSE_MATRIX */ 10139 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10140 } 10141 10142 PetscCall(MatProductNumeric(*C)); 10143 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10144 PetscFunctionReturn(PETSC_SUCCESS); 10145 } 10146 10147 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10148 { 10149 PetscBool flg = PETSC_TRUE; 10150 10151 PetscFunctionBegin; 10152 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10153 if (scall == MAT_INITIAL_MATRIX) { 10154 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10155 PetscCall(MatProductCreate(A, B, NULL, C)); 10156 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10157 PetscCall(MatProductSetFill(*C, fill)); 10158 } else { /* scall == MAT_REUSE_MATRIX */ 10159 Mat_Product *product = (*C)->product; 10160 10161 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10162 if (flg && product && product->type != ptype) { 10163 PetscCall(MatProductClear(*C)); 10164 product = NULL; 10165 } 10166 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10167 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10168 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10169 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10170 product = (*C)->product; 10171 product->fill = fill; 10172 product->clear = PETSC_TRUE; 10173 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10174 flg = PETSC_FALSE; 10175 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10176 } 10177 } 10178 if (flg) { 10179 (*C)->product->api_user = PETSC_TRUE; 10180 PetscCall(MatProductSetType(*C, ptype)); 10181 PetscCall(MatProductSetFromOptions(*C)); 10182 PetscCall(MatProductSymbolic(*C)); 10183 } 10184 PetscCall(MatProductNumeric(*C)); 10185 PetscFunctionReturn(PETSC_SUCCESS); 10186 } 10187 10188 /*@ 10189 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10190 10191 Neighbor-wise Collective 10192 10193 Input Parameters: 10194 + A - the left matrix 10195 . B - the right matrix 10196 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10197 - 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 10198 if the result is a dense matrix this is irrelevant 10199 10200 Output Parameter: 10201 . C - the product matrix 10202 10203 Notes: 10204 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10205 10206 `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 10207 call to this function with `MAT_INITIAL_MATRIX`. 10208 10209 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10210 10211 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`, 10212 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10213 10214 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10215 10216 Example of Usage: 10217 .vb 10218 MatProductCreate(A,B,NULL,&C); 10219 MatProductSetType(C,MATPRODUCT_AB); 10220 MatProductSymbolic(C); 10221 MatProductNumeric(C); // compute C=A * B 10222 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10223 MatProductNumeric(C); 10224 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10225 MatProductNumeric(C); 10226 .ve 10227 10228 Level: intermediate 10229 10230 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10231 @*/ 10232 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10233 { 10234 PetscFunctionBegin; 10235 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10236 PetscFunctionReturn(PETSC_SUCCESS); 10237 } 10238 10239 /*@ 10240 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10241 10242 Neighbor-wise Collective 10243 10244 Input Parameters: 10245 + A - the left matrix 10246 . B - the right matrix 10247 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10248 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10249 10250 Output Parameter: 10251 . C - the product matrix 10252 10253 Options Database Key: 10254 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10255 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10256 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10257 10258 Level: intermediate 10259 10260 Notes: 10261 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10262 10263 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10264 10265 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10266 actually needed. 10267 10268 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10269 and for pairs of `MATMPIDENSE` matrices. 10270 10271 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10272 10273 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10274 10275 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10276 @*/ 10277 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10278 { 10279 PetscFunctionBegin; 10280 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10281 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10282 PetscFunctionReturn(PETSC_SUCCESS); 10283 } 10284 10285 /*@ 10286 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10287 10288 Neighbor-wise Collective 10289 10290 Input Parameters: 10291 + A - the left matrix 10292 . B - the right matrix 10293 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10294 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10295 10296 Output Parameter: 10297 . C - the product matrix 10298 10299 Level: intermediate 10300 10301 Notes: 10302 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10303 10304 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10305 10306 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10307 10308 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10309 actually needed. 10310 10311 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10312 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10313 10314 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10315 10316 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10317 @*/ 10318 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10319 { 10320 PetscFunctionBegin; 10321 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10322 PetscFunctionReturn(PETSC_SUCCESS); 10323 } 10324 10325 /*@ 10326 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10327 10328 Neighbor-wise Collective 10329 10330 Input Parameters: 10331 + A - the left matrix 10332 . B - the middle matrix 10333 . C - the right matrix 10334 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10335 - 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 10336 if the result is a dense matrix this is irrelevant 10337 10338 Output Parameter: 10339 . D - the product matrix 10340 10341 Level: intermediate 10342 10343 Notes: 10344 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10345 10346 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10347 10348 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10349 10350 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10351 actually needed. 10352 10353 If you have many matrices with the same non-zero structure to multiply, you 10354 should use `MAT_REUSE_MATRIX` in all calls but the first 10355 10356 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10357 10358 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10359 @*/ 10360 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10361 { 10362 PetscFunctionBegin; 10363 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10364 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10365 10366 if (scall == MAT_INITIAL_MATRIX) { 10367 PetscCall(MatProductCreate(A, B, C, D)); 10368 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10369 PetscCall(MatProductSetAlgorithm(*D, "default")); 10370 PetscCall(MatProductSetFill(*D, fill)); 10371 10372 (*D)->product->api_user = PETSC_TRUE; 10373 PetscCall(MatProductSetFromOptions(*D)); 10374 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, 10375 ((PetscObject)C)->type_name); 10376 PetscCall(MatProductSymbolic(*D)); 10377 } else { /* user may change input matrices when REUSE */ 10378 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10379 } 10380 PetscCall(MatProductNumeric(*D)); 10381 PetscFunctionReturn(PETSC_SUCCESS); 10382 } 10383 10384 /*@ 10385 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10386 10387 Collective 10388 10389 Input Parameters: 10390 + mat - the matrix 10391 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10392 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10393 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10394 10395 Output Parameter: 10396 . matredundant - redundant matrix 10397 10398 Level: advanced 10399 10400 Notes: 10401 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10402 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10403 10404 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10405 calling it. 10406 10407 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10408 10409 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10410 @*/ 10411 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10412 { 10413 MPI_Comm comm; 10414 PetscMPIInt size; 10415 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10416 Mat_Redundant *redund = NULL; 10417 PetscSubcomm psubcomm = NULL; 10418 MPI_Comm subcomm_in = subcomm; 10419 Mat *matseq; 10420 IS isrow, iscol; 10421 PetscBool newsubcomm = PETSC_FALSE; 10422 10423 PetscFunctionBegin; 10424 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10425 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10426 PetscAssertPointer(*matredundant, 5); 10427 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10428 } 10429 10430 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10431 if (size == 1 || nsubcomm == 1) { 10432 if (reuse == MAT_INITIAL_MATRIX) { 10433 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10434 } else { 10435 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"); 10436 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10437 } 10438 PetscFunctionReturn(PETSC_SUCCESS); 10439 } 10440 10441 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10442 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10443 MatCheckPreallocated(mat, 1); 10444 10445 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10446 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10447 /* create psubcomm, then get subcomm */ 10448 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10449 PetscCallMPI(MPI_Comm_size(comm, &size)); 10450 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10451 10452 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10453 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10454 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10455 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10456 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10457 newsubcomm = PETSC_TRUE; 10458 PetscCall(PetscSubcommDestroy(&psubcomm)); 10459 } 10460 10461 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10462 if (reuse == MAT_INITIAL_MATRIX) { 10463 mloc_sub = PETSC_DECIDE; 10464 nloc_sub = PETSC_DECIDE; 10465 if (bs < 1) { 10466 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10467 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10468 } else { 10469 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10470 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10471 } 10472 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10473 rstart = rend - mloc_sub; 10474 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10475 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10476 PetscCall(ISSetIdentity(iscol)); 10477 } else { /* reuse == MAT_REUSE_MATRIX */ 10478 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"); 10479 /* retrieve subcomm */ 10480 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10481 redund = (*matredundant)->redundant; 10482 isrow = redund->isrow; 10483 iscol = redund->iscol; 10484 matseq = redund->matseq; 10485 } 10486 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10487 10488 /* get matredundant over subcomm */ 10489 if (reuse == MAT_INITIAL_MATRIX) { 10490 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10491 10492 /* create a supporting struct and attach it to C for reuse */ 10493 PetscCall(PetscNew(&redund)); 10494 (*matredundant)->redundant = redund; 10495 redund->isrow = isrow; 10496 redund->iscol = iscol; 10497 redund->matseq = matseq; 10498 if (newsubcomm) { 10499 redund->subcomm = subcomm; 10500 } else { 10501 redund->subcomm = MPI_COMM_NULL; 10502 } 10503 } else { 10504 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10505 } 10506 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10507 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10508 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10509 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10510 } 10511 #endif 10512 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10513 PetscFunctionReturn(PETSC_SUCCESS); 10514 } 10515 10516 /*@C 10517 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10518 a given `Mat`. Each submatrix can span multiple procs. 10519 10520 Collective 10521 10522 Input Parameters: 10523 + mat - the matrix 10524 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10525 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10526 10527 Output Parameter: 10528 . subMat - parallel sub-matrices each spanning a given `subcomm` 10529 10530 Level: advanced 10531 10532 Notes: 10533 The submatrix partition across processors is dictated by `subComm` a 10534 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10535 is not restricted to be grouped with consecutive original MPI processes. 10536 10537 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10538 map directly to the layout of the original matrix [wrt the local 10539 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10540 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10541 the `subMat`. However the offDiagMat looses some columns - and this is 10542 reconstructed with `MatSetValues()` 10543 10544 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10545 10546 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10547 @*/ 10548 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10549 { 10550 PetscMPIInt commsize, subCommSize; 10551 10552 PetscFunctionBegin; 10553 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10554 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10555 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10556 10557 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"); 10558 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10559 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10560 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10561 PetscFunctionReturn(PETSC_SUCCESS); 10562 } 10563 10564 /*@ 10565 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10566 10567 Not Collective 10568 10569 Input Parameters: 10570 + mat - matrix to extract local submatrix from 10571 . isrow - local row indices for submatrix 10572 - iscol - local column indices for submatrix 10573 10574 Output Parameter: 10575 . submat - the submatrix 10576 10577 Level: intermediate 10578 10579 Notes: 10580 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10581 10582 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10583 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10584 10585 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10586 `MatSetValuesBlockedLocal()` will also be implemented. 10587 10588 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10589 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10590 10591 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10592 @*/ 10593 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10594 { 10595 PetscFunctionBegin; 10596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10597 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10598 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10599 PetscCheckSameComm(isrow, 2, iscol, 3); 10600 PetscAssertPointer(submat, 4); 10601 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10602 10603 if (mat->ops->getlocalsubmatrix) { 10604 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10605 } else { 10606 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10607 } 10608 PetscFunctionReturn(PETSC_SUCCESS); 10609 } 10610 10611 /*@ 10612 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10613 10614 Not Collective 10615 10616 Input Parameters: 10617 + mat - matrix to extract local submatrix from 10618 . isrow - local row indices for submatrix 10619 . iscol - local column indices for submatrix 10620 - submat - the submatrix 10621 10622 Level: intermediate 10623 10624 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10625 @*/ 10626 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10627 { 10628 PetscFunctionBegin; 10629 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10630 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10631 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10632 PetscCheckSameComm(isrow, 2, iscol, 3); 10633 PetscAssertPointer(submat, 4); 10634 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10635 10636 if (mat->ops->restorelocalsubmatrix) { 10637 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10638 } else { 10639 PetscCall(MatDestroy(submat)); 10640 } 10641 *submat = NULL; 10642 PetscFunctionReturn(PETSC_SUCCESS); 10643 } 10644 10645 /*@ 10646 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10647 10648 Collective 10649 10650 Input Parameter: 10651 . mat - the matrix 10652 10653 Output Parameter: 10654 . is - if any rows have zero diagonals this contains the list of them 10655 10656 Level: developer 10657 10658 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10659 @*/ 10660 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10661 { 10662 PetscFunctionBegin; 10663 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10664 PetscValidType(mat, 1); 10665 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10666 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10667 10668 if (!mat->ops->findzerodiagonals) { 10669 Vec diag; 10670 const PetscScalar *a; 10671 PetscInt *rows; 10672 PetscInt rStart, rEnd, r, nrow = 0; 10673 10674 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10675 PetscCall(MatGetDiagonal(mat, diag)); 10676 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10677 PetscCall(VecGetArrayRead(diag, &a)); 10678 for (r = 0; r < rEnd - rStart; ++r) 10679 if (a[r] == 0.0) ++nrow; 10680 PetscCall(PetscMalloc1(nrow, &rows)); 10681 nrow = 0; 10682 for (r = 0; r < rEnd - rStart; ++r) 10683 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10684 PetscCall(VecRestoreArrayRead(diag, &a)); 10685 PetscCall(VecDestroy(&diag)); 10686 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10687 } else { 10688 PetscUseTypeMethod(mat, findzerodiagonals, is); 10689 } 10690 PetscFunctionReturn(PETSC_SUCCESS); 10691 } 10692 10693 /*@ 10694 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10695 10696 Collective 10697 10698 Input Parameter: 10699 . mat - the matrix 10700 10701 Output Parameter: 10702 . is - contains the list of rows with off block diagonal entries 10703 10704 Level: developer 10705 10706 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10707 @*/ 10708 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10709 { 10710 PetscFunctionBegin; 10711 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10712 PetscValidType(mat, 1); 10713 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10714 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10715 10716 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10717 PetscFunctionReturn(PETSC_SUCCESS); 10718 } 10719 10720 /*@C 10721 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10722 10723 Collective; No Fortran Support 10724 10725 Input Parameter: 10726 . mat - the matrix 10727 10728 Output Parameter: 10729 . values - the block inverses in column major order (FORTRAN-like) 10730 10731 Level: advanced 10732 10733 Notes: 10734 The size of the blocks is determined by the block size of the matrix. 10735 10736 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10737 10738 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10739 10740 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10741 @*/ 10742 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10743 { 10744 PetscFunctionBegin; 10745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10746 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10747 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10748 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10749 PetscFunctionReturn(PETSC_SUCCESS); 10750 } 10751 10752 /*@ 10753 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10754 10755 Collective; No Fortran Support 10756 10757 Input Parameters: 10758 + mat - the matrix 10759 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10760 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10761 10762 Output Parameter: 10763 . values - the block inverses in column major order (FORTRAN-like) 10764 10765 Level: advanced 10766 10767 Notes: 10768 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10769 10770 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10771 10772 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10773 @*/ 10774 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10775 { 10776 PetscFunctionBegin; 10777 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10778 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10779 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10780 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10781 PetscFunctionReturn(PETSC_SUCCESS); 10782 } 10783 10784 /*@ 10785 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10786 10787 Collective 10788 10789 Input Parameters: 10790 + A - the matrix 10791 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10792 10793 Level: advanced 10794 10795 Note: 10796 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10797 10798 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10799 @*/ 10800 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10801 { 10802 const PetscScalar *vals; 10803 PetscInt *dnnz; 10804 PetscInt m, rstart, rend, bs, i, j; 10805 10806 PetscFunctionBegin; 10807 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10808 PetscCall(MatGetBlockSize(A, &bs)); 10809 PetscCall(MatGetLocalSize(A, &m, NULL)); 10810 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10811 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10812 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10813 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10814 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10815 PetscCall(PetscFree(dnnz)); 10816 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10817 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10818 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10819 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10820 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10821 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10822 PetscFunctionReturn(PETSC_SUCCESS); 10823 } 10824 10825 /*@ 10826 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10827 via `MatTransposeColoringCreate()`. 10828 10829 Collective 10830 10831 Input Parameter: 10832 . c - coloring context 10833 10834 Level: intermediate 10835 10836 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10837 @*/ 10838 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10839 { 10840 MatTransposeColoring matcolor = *c; 10841 10842 PetscFunctionBegin; 10843 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10844 if (--((PetscObject)matcolor)->refct > 0) { 10845 matcolor = NULL; 10846 PetscFunctionReturn(PETSC_SUCCESS); 10847 } 10848 10849 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10850 PetscCall(PetscFree(matcolor->rows)); 10851 PetscCall(PetscFree(matcolor->den2sp)); 10852 PetscCall(PetscFree(matcolor->colorforcol)); 10853 PetscCall(PetscFree(matcolor->columns)); 10854 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10855 PetscCall(PetscHeaderDestroy(c)); 10856 PetscFunctionReturn(PETSC_SUCCESS); 10857 } 10858 10859 /*@ 10860 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10861 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10862 `MatTransposeColoring` to sparse `B`. 10863 10864 Collective 10865 10866 Input Parameters: 10867 + coloring - coloring context created with `MatTransposeColoringCreate()` 10868 - B - sparse matrix 10869 10870 Output Parameter: 10871 . Btdense - dense matrix $B^T$ 10872 10873 Level: developer 10874 10875 Note: 10876 These are used internally for some implementations of `MatRARt()` 10877 10878 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10879 @*/ 10880 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10881 { 10882 PetscFunctionBegin; 10883 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10884 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10885 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10886 10887 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10888 PetscFunctionReturn(PETSC_SUCCESS); 10889 } 10890 10891 /*@ 10892 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10893 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10894 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10895 $C_{sp}$ from $C_{den}$. 10896 10897 Collective 10898 10899 Input Parameters: 10900 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10901 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10902 10903 Output Parameter: 10904 . Csp - sparse matrix 10905 10906 Level: developer 10907 10908 Note: 10909 These are used internally for some implementations of `MatRARt()` 10910 10911 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10912 @*/ 10913 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10914 { 10915 PetscFunctionBegin; 10916 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10917 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10918 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10919 10920 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10921 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10922 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10923 PetscFunctionReturn(PETSC_SUCCESS); 10924 } 10925 10926 /*@ 10927 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10928 10929 Collective 10930 10931 Input Parameters: 10932 + mat - the matrix product C 10933 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10934 10935 Output Parameter: 10936 . color - the new coloring context 10937 10938 Level: intermediate 10939 10940 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10941 `MatTransColoringApplyDenToSp()` 10942 @*/ 10943 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10944 { 10945 MatTransposeColoring c; 10946 MPI_Comm comm; 10947 10948 PetscFunctionBegin; 10949 PetscAssertPointer(color, 3); 10950 10951 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10952 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10953 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10954 c->ctype = iscoloring->ctype; 10955 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10956 *color = c; 10957 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10958 PetscFunctionReturn(PETSC_SUCCESS); 10959 } 10960 10961 /*@ 10962 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10963 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10964 10965 Not Collective 10966 10967 Input Parameter: 10968 . mat - the matrix 10969 10970 Output Parameter: 10971 . state - the current state 10972 10973 Level: intermediate 10974 10975 Notes: 10976 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10977 different matrices 10978 10979 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10980 10981 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10982 10983 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10984 @*/ 10985 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10986 { 10987 PetscFunctionBegin; 10988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10989 *state = mat->nonzerostate; 10990 PetscFunctionReturn(PETSC_SUCCESS); 10991 } 10992 10993 /*@ 10994 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10995 matrices from each processor 10996 10997 Collective 10998 10999 Input Parameters: 11000 + comm - the communicators the parallel matrix will live on 11001 . seqmat - the input sequential matrices 11002 . n - number of local columns (or `PETSC_DECIDE`) 11003 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11004 11005 Output Parameter: 11006 . mpimat - the parallel matrix generated 11007 11008 Level: developer 11009 11010 Note: 11011 The number of columns of the matrix in EACH processor MUST be the same. 11012 11013 .seealso: [](ch_matrices), `Mat` 11014 @*/ 11015 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11016 { 11017 PetscMPIInt size; 11018 11019 PetscFunctionBegin; 11020 PetscCallMPI(MPI_Comm_size(comm, &size)); 11021 if (size == 1) { 11022 if (reuse == MAT_INITIAL_MATRIX) { 11023 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11024 } else { 11025 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11026 } 11027 PetscFunctionReturn(PETSC_SUCCESS); 11028 } 11029 11030 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"); 11031 11032 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11033 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11034 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11035 PetscFunctionReturn(PETSC_SUCCESS); 11036 } 11037 11038 /*@ 11039 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11040 11041 Collective 11042 11043 Input Parameters: 11044 + A - the matrix to create subdomains from 11045 - N - requested number of subdomains 11046 11047 Output Parameters: 11048 + n - number of subdomains resulting on this MPI process 11049 - iss - `IS` list with indices of subdomains on this MPI process 11050 11051 Level: advanced 11052 11053 Note: 11054 The number of subdomains must be smaller than the communicator size 11055 11056 .seealso: [](ch_matrices), `Mat`, `IS` 11057 @*/ 11058 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11059 { 11060 MPI_Comm comm, subcomm; 11061 PetscMPIInt size, rank, color; 11062 PetscInt rstart, rend, k; 11063 11064 PetscFunctionBegin; 11065 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11066 PetscCallMPI(MPI_Comm_size(comm, &size)); 11067 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11068 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); 11069 *n = 1; 11070 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11071 color = rank / k; 11072 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11073 PetscCall(PetscMalloc1(1, iss)); 11074 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11075 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11076 PetscCallMPI(MPI_Comm_free(&subcomm)); 11077 PetscFunctionReturn(PETSC_SUCCESS); 11078 } 11079 11080 /*@ 11081 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11082 11083 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11084 If they are not the same, uses `MatMatMatMult()`. 11085 11086 Once the coarse grid problem is constructed, correct for interpolation operators 11087 that are not of full rank, which can legitimately happen in the case of non-nested 11088 geometric multigrid. 11089 11090 Input Parameters: 11091 + restrct - restriction operator 11092 . dA - fine grid matrix 11093 . interpolate - interpolation operator 11094 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11095 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11096 11097 Output Parameter: 11098 . A - the Galerkin coarse matrix 11099 11100 Options Database Key: 11101 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11102 11103 Level: developer 11104 11105 Note: 11106 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11107 11108 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11109 @*/ 11110 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11111 { 11112 IS zerorows; 11113 Vec diag; 11114 11115 PetscFunctionBegin; 11116 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11117 /* Construct the coarse grid matrix */ 11118 if (interpolate == restrct) { 11119 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11120 } else { 11121 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11122 } 11123 11124 /* If the interpolation matrix is not of full rank, A will have zero rows. 11125 This can legitimately happen in the case of non-nested geometric multigrid. 11126 In that event, we set the rows of the matrix to the rows of the identity, 11127 ignoring the equations (as the RHS will also be zero). */ 11128 11129 PetscCall(MatFindZeroRows(*A, &zerorows)); 11130 11131 if (zerorows != NULL) { /* if there are any zero rows */ 11132 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11133 PetscCall(MatGetDiagonal(*A, diag)); 11134 PetscCall(VecISSet(diag, zerorows, 1.0)); 11135 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11136 PetscCall(VecDestroy(&diag)); 11137 PetscCall(ISDestroy(&zerorows)); 11138 } 11139 PetscFunctionReturn(PETSC_SUCCESS); 11140 } 11141 11142 /*@C 11143 MatSetOperation - Allows user to set a matrix operation for any matrix type 11144 11145 Logically Collective 11146 11147 Input Parameters: 11148 + mat - the matrix 11149 . op - the name of the operation 11150 - f - the function that provides the operation 11151 11152 Level: developer 11153 11154 Example Usage: 11155 .vb 11156 extern PetscErrorCode usermult(Mat, Vec, Vec); 11157 11158 PetscCall(MatCreateXXX(comm, ..., &A)); 11159 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11160 .ve 11161 11162 Notes: 11163 See the file `include/petscmat.h` for a complete list of matrix 11164 operations, which all have the form MATOP_<OPERATION>, where 11165 <OPERATION> is the name (in all capital letters) of the 11166 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11167 11168 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11169 sequence as the usual matrix interface routines, since they 11170 are intended to be accessed via the usual matrix interface 11171 routines, e.g., 11172 .vb 11173 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11174 .ve 11175 11176 In particular each function MUST return `PETSC_SUCCESS` on success and 11177 nonzero on failure. 11178 11179 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11180 11181 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11182 @*/ 11183 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11184 { 11185 PetscFunctionBegin; 11186 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11187 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11188 (((void (**)(void))mat->ops)[op]) = f; 11189 PetscFunctionReturn(PETSC_SUCCESS); 11190 } 11191 11192 /*@C 11193 MatGetOperation - Gets a matrix operation for any matrix type. 11194 11195 Not Collective 11196 11197 Input Parameters: 11198 + mat - the matrix 11199 - op - the name of the operation 11200 11201 Output Parameter: 11202 . f - the function that provides the operation 11203 11204 Level: developer 11205 11206 Example Usage: 11207 .vb 11208 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11209 11210 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11211 .ve 11212 11213 Notes: 11214 See the file include/petscmat.h for a complete list of matrix 11215 operations, which all have the form MATOP_<OPERATION>, where 11216 <OPERATION> is the name (in all capital letters) of the 11217 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11218 11219 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11220 11221 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11222 @*/ 11223 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11224 { 11225 PetscFunctionBegin; 11226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11227 *f = (((void (**)(void))mat->ops)[op]); 11228 PetscFunctionReturn(PETSC_SUCCESS); 11229 } 11230 11231 /*@ 11232 MatHasOperation - Determines whether the given matrix supports the particular operation. 11233 11234 Not Collective 11235 11236 Input Parameters: 11237 + mat - the matrix 11238 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11239 11240 Output Parameter: 11241 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11242 11243 Level: advanced 11244 11245 Note: 11246 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11247 11248 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11249 @*/ 11250 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11251 { 11252 PetscFunctionBegin; 11253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11254 PetscAssertPointer(has, 3); 11255 if (mat->ops->hasoperation) { 11256 PetscUseTypeMethod(mat, hasoperation, op, has); 11257 } else { 11258 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11259 else { 11260 *has = PETSC_FALSE; 11261 if (op == MATOP_CREATE_SUBMATRIX) { 11262 PetscMPIInt size; 11263 11264 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11265 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11266 } 11267 } 11268 } 11269 PetscFunctionReturn(PETSC_SUCCESS); 11270 } 11271 11272 /*@ 11273 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11274 11275 Collective 11276 11277 Input Parameter: 11278 . mat - the matrix 11279 11280 Output Parameter: 11281 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11282 11283 Level: beginner 11284 11285 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11286 @*/ 11287 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11288 { 11289 PetscFunctionBegin; 11290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11291 PetscValidType(mat, 1); 11292 PetscAssertPointer(cong, 2); 11293 if (!mat->rmap || !mat->cmap) { 11294 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11295 PetscFunctionReturn(PETSC_SUCCESS); 11296 } 11297 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11298 PetscCall(PetscLayoutSetUp(mat->rmap)); 11299 PetscCall(PetscLayoutSetUp(mat->cmap)); 11300 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11301 if (*cong) mat->congruentlayouts = 1; 11302 else mat->congruentlayouts = 0; 11303 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11304 PetscFunctionReturn(PETSC_SUCCESS); 11305 } 11306 11307 PetscErrorCode MatSetInf(Mat A) 11308 { 11309 PetscFunctionBegin; 11310 PetscUseTypeMethod(A, setinf); 11311 PetscFunctionReturn(PETSC_SUCCESS); 11312 } 11313 11314 /*@ 11315 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 11316 and possibly removes small values from the graph structure. 11317 11318 Collective 11319 11320 Input Parameters: 11321 + A - the matrix 11322 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11323 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11324 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11325 . num_idx - size of 'index' array 11326 - index - array of block indices to use for graph strength of connection weight 11327 11328 Output Parameter: 11329 . graph - the resulting graph 11330 11331 Level: advanced 11332 11333 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11334 @*/ 11335 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11336 { 11337 PetscFunctionBegin; 11338 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11339 PetscValidType(A, 1); 11340 PetscValidLogicalCollectiveBool(A, scale, 3); 11341 PetscAssertPointer(graph, 7); 11342 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11343 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11344 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11345 PetscFunctionReturn(PETSC_SUCCESS); 11346 } 11347 11348 /*@ 11349 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11350 meaning the same memory is used for the matrix, and no new memory is allocated. 11351 11352 Collective 11353 11354 Input Parameters: 11355 + A - the matrix 11356 - 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 11357 11358 Level: intermediate 11359 11360 Developer Note: 11361 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11362 of the arrays in the data structure are unneeded. 11363 11364 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11365 @*/ 11366 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11367 { 11368 PetscFunctionBegin; 11369 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11370 PetscUseTypeMethod(A, eliminatezeros, keep); 11371 PetscFunctionReturn(PETSC_SUCCESS); 11372 } 11373