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