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