1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscFunctionReturn(PETSC_SUCCESS); 759 } 760 761 /*@ 762 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 763 for matrices created with `MatGetFactor()` 764 765 Logically Collective 766 767 Input Parameters: 768 + A - the matrix 769 - prefix - the prefix to prepend to all option names for the factored matrix 770 771 Level: developer 772 773 Notes: 774 A hyphen (-) must NOT be given at the beginning of the prefix name. 775 The first character of all runtime options is AUTOMATICALLY the hyphen. 776 777 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 778 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 779 780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 781 @*/ 782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 783 { 784 PetscFunctionBegin; 785 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 786 if (prefix) { 787 PetscAssertPointer(prefix, 2); 788 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 789 if (prefix != A->factorprefix) { 790 PetscCall(PetscFree(A->factorprefix)); 791 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 792 } 793 } else PetscCall(PetscFree(A->factorprefix)); 794 PetscFunctionReturn(PETSC_SUCCESS); 795 } 796 797 /*@ 798 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 799 for matrices created with `MatGetFactor()` 800 801 Logically Collective 802 803 Input Parameters: 804 + A - the matrix 805 - prefix - the prefix to prepend to all option names for the factored matrix 806 807 Level: developer 808 809 Notes: 810 A hyphen (-) must NOT be given at the beginning of the prefix name. 811 The first character of all runtime options is AUTOMATICALLY the hyphen. 812 813 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 814 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 815 816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 817 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 818 `MatSetOptionsPrefix()` 819 @*/ 820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 821 { 822 size_t len1, len2, new_len; 823 824 PetscFunctionBegin; 825 PetscValidHeader(A, 1); 826 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 827 if (!A->factorprefix) { 828 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 829 PetscFunctionReturn(PETSC_SUCCESS); 830 } 831 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 832 833 PetscCall(PetscStrlen(A->factorprefix, &len1)); 834 PetscCall(PetscStrlen(prefix, &len2)); 835 new_len = len1 + len2 + 1; 836 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 837 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@ 842 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 843 matrix options in the database. 844 845 Logically Collective 846 847 Input Parameters: 848 + A - the matrix 849 - prefix - the prefix to prepend to all option names 850 851 Level: advanced 852 853 Note: 854 A hyphen (-) must NOT be given at the beginning of the prefix name. 855 The first character of all runtime options is AUTOMATICALLY the hyphen. 856 857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 858 @*/ 859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 860 { 861 PetscFunctionBegin; 862 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 863 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 864 PetscFunctionReturn(PETSC_SUCCESS); 865 } 866 867 /*@ 868 MatGetOptionsPrefix - Gets the prefix used for searching for all 869 matrix options in the database. 870 871 Not Collective 872 873 Input Parameter: 874 . A - the matrix 875 876 Output Parameter: 877 . prefix - pointer to the prefix string used 878 879 Level: advanced 880 881 Fortran Note: 882 The user should pass in a string `prefix` of 883 sufficient length to hold the prefix. 884 885 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 886 @*/ 887 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 888 { 889 PetscFunctionBegin; 890 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 891 PetscAssertPointer(prefix, 2); 892 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 893 PetscFunctionReturn(PETSC_SUCCESS); 894 } 895 896 /*@ 897 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 898 899 Not Collective 900 901 Input Parameter: 902 . A - the matrix 903 904 Output Parameter: 905 . state - the object state 906 907 Level: advanced 908 909 Note: 910 Object state is an integer which gets increased every time 911 the object is changed. By saving and later querying the object state 912 one can determine whether information about the object is still current. 913 914 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 915 916 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 917 @*/ 918 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 919 { 920 PetscFunctionBegin; 921 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 922 PetscAssertPointer(state, 2); 923 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 924 PetscFunctionReturn(PETSC_SUCCESS); 925 } 926 927 /*@ 928 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 929 930 Collective 931 932 Input Parameter: 933 . A - the matrix 934 935 Level: beginner 936 937 Notes: 938 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 939 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 940 makes all of the preallocation space available 941 942 Current values in the matrix are lost in this call 943 944 Currently only supported for `MATAIJ` matrices. 945 946 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 947 @*/ 948 PetscErrorCode MatResetPreallocation(Mat A) 949 { 950 PetscFunctionBegin; 951 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 952 PetscValidType(A, 1); 953 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 954 PetscFunctionReturn(PETSC_SUCCESS); 955 } 956 957 /*@ 958 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 959 960 Collective 961 962 Input Parameter: 963 . A - the matrix 964 965 Level: intermediate 966 967 Notes: 968 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 969 970 Currently only supported for `MATAIJ` matrices. 971 972 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 973 @*/ 974 PetscErrorCode MatResetHash(Mat A) 975 { 976 PetscFunctionBegin; 977 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 978 PetscValidType(A, 1); 979 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()"); 980 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 981 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 982 /* These flags are used to determine whether certain setups occur */ 983 A->was_assembled = PETSC_FALSE; 984 A->assembled = PETSC_FALSE; 985 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 986 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 987 PetscFunctionReturn(PETSC_SUCCESS); 988 } 989 990 /*@ 991 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 992 993 Collective 994 995 Input Parameter: 996 . A - the matrix 997 998 Level: advanced 999 1000 Notes: 1001 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1002 setting values in the matrix. 1003 1004 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1005 1006 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1007 @*/ 1008 PetscErrorCode MatSetUp(Mat A) 1009 { 1010 PetscFunctionBegin; 1011 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1012 if (!((PetscObject)A)->type_name) { 1013 PetscMPIInt size; 1014 1015 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1016 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1017 } 1018 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1019 PetscCall(PetscLayoutSetUp(A->rmap)); 1020 PetscCall(PetscLayoutSetUp(A->cmap)); 1021 A->preallocated = PETSC_TRUE; 1022 PetscFunctionReturn(PETSC_SUCCESS); 1023 } 1024 1025 #if defined(PETSC_HAVE_SAWS) 1026 #include <petscviewersaws.h> 1027 #endif 1028 1029 /* 1030 If threadsafety is on extraneous matrices may be printed 1031 1032 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1033 */ 1034 #if !defined(PETSC_HAVE_THREADSAFETY) 1035 static PetscInt insidematview = 0; 1036 #endif 1037 1038 /*@ 1039 MatViewFromOptions - View properties of the matrix based on options set in the options database 1040 1041 Collective 1042 1043 Input Parameters: 1044 + A - the matrix 1045 . obj - optional additional object that provides the options prefix to use 1046 - name - command line option 1047 1048 Options Database Key: 1049 . -mat_view [viewertype]:... - the viewer and its options 1050 1051 Level: intermediate 1052 1053 Note: 1054 .vb 1055 If no value is provided ascii:stdout is used 1056 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1057 for example ascii::ascii_info prints just the information about the object not all details 1058 unless :append is given filename opens in write mode, overwriting what was already there 1059 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1060 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1061 socket[:port] defaults to the standard output port 1062 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1063 .ve 1064 1065 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1066 @*/ 1067 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1068 { 1069 PetscFunctionBegin; 1070 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1071 #if !defined(PETSC_HAVE_THREADSAFETY) 1072 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1073 #endif 1074 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1075 PetscFunctionReturn(PETSC_SUCCESS); 1076 } 1077 1078 /*@ 1079 MatView - display information about a matrix in a variety ways 1080 1081 Collective on viewer 1082 1083 Input Parameters: 1084 + mat - the matrix 1085 - viewer - visualization context 1086 1087 Options Database Keys: 1088 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1089 . -mat_view ::ascii_info_detail - Prints more detailed info 1090 . -mat_view - Prints matrix in ASCII format 1091 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1092 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1093 . -display <name> - Sets display name (default is host) 1094 . -draw_pause <sec> - Sets number of seconds to pause after display 1095 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1096 . -viewer_socket_machine <machine> - - 1097 . -viewer_socket_port <port> - - 1098 . -mat_view binary - save matrix to file in binary format 1099 - -viewer_binary_filename <name> - - 1100 1101 Level: beginner 1102 1103 Notes: 1104 The available visualization contexts include 1105 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1106 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1107 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1108 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1109 1110 The user can open alternative visualization contexts with 1111 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1112 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1113 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1114 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1115 1116 The user can call `PetscViewerPushFormat()` to specify the output 1117 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1118 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1119 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1120 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1121 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1122 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1123 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1124 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1125 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1126 1127 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1128 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1129 1130 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1131 1132 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1133 viewer is used. 1134 1135 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1136 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1137 1138 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1139 and then use the following mouse functions. 1140 .vb 1141 left mouse: zoom in 1142 middle mouse: zoom out 1143 right mouse: continue with the simulation 1144 .ve 1145 1146 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1147 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1148 @*/ 1149 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1150 { 1151 PetscInt rows, cols, rbs, cbs; 1152 PetscBool isascii, isstring, issaws; 1153 PetscViewerFormat format; 1154 PetscMPIInt size; 1155 1156 PetscFunctionBegin; 1157 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1158 PetscValidType(mat, 1); 1159 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1160 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1161 1162 PetscCall(PetscViewerGetFormat(viewer, &format)); 1163 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1164 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1165 1166 #if !defined(PETSC_HAVE_THREADSAFETY) 1167 insidematview++; 1168 #endif 1169 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1170 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1171 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1172 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"); 1173 1174 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1175 if (isascii) { 1176 if (!mat->preallocated) { 1177 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1178 #if !defined(PETSC_HAVE_THREADSAFETY) 1179 insidematview--; 1180 #endif 1181 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1182 PetscFunctionReturn(PETSC_SUCCESS); 1183 } 1184 if (!mat->assembled) { 1185 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1186 #if !defined(PETSC_HAVE_THREADSAFETY) 1187 insidematview--; 1188 #endif 1189 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1190 PetscFunctionReturn(PETSC_SUCCESS); 1191 } 1192 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1193 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1194 MatNullSpace nullsp, transnullsp; 1195 1196 PetscCall(PetscViewerASCIIPushTab(viewer)); 1197 PetscCall(MatGetSize(mat, &rows, &cols)); 1198 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1199 if (rbs != 1 || cbs != 1) { 1200 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" : "")); 1201 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1202 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1203 if (mat->factortype) { 1204 MatSolverType solver; 1205 PetscCall(MatFactorGetSolverType(mat, &solver)); 1206 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1207 } 1208 if (mat->ops->getinfo) { 1209 MatInfo info; 1210 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1211 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1212 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1213 } 1214 PetscCall(MatGetNullSpace(mat, &nullsp)); 1215 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1216 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1217 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1218 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1219 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1220 PetscCall(PetscViewerASCIIPushTab(viewer)); 1221 PetscCall(MatProductView(mat, viewer)); 1222 PetscCall(PetscViewerASCIIPopTab(viewer)); 1223 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1224 IS tmp; 1225 1226 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1227 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1228 PetscCall(PetscViewerASCIIPushTab(viewer)); 1229 PetscCall(ISView(tmp, viewer)); 1230 PetscCall(PetscViewerASCIIPopTab(viewer)); 1231 PetscCall(ISDestroy(&tmp)); 1232 } 1233 } 1234 } else if (issaws) { 1235 #if defined(PETSC_HAVE_SAWS) 1236 PetscMPIInt rank; 1237 1238 PetscCall(PetscObjectName((PetscObject)mat)); 1239 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1240 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1241 #endif 1242 } else if (isstring) { 1243 const char *type; 1244 PetscCall(MatGetType(mat, &type)); 1245 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1246 PetscTryTypeMethod(mat, view, viewer); 1247 } 1248 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1249 PetscCall(PetscViewerASCIIPushTab(viewer)); 1250 PetscUseTypeMethod(mat, viewnative, viewer); 1251 PetscCall(PetscViewerASCIIPopTab(viewer)); 1252 } else if (mat->ops->view) { 1253 PetscCall(PetscViewerASCIIPushTab(viewer)); 1254 PetscUseTypeMethod(mat, view, viewer); 1255 PetscCall(PetscViewerASCIIPopTab(viewer)); 1256 } 1257 if (isascii) { 1258 PetscCall(PetscViewerGetFormat(viewer, &format)); 1259 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1260 } 1261 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1262 #if !defined(PETSC_HAVE_THREADSAFETY) 1263 insidematview--; 1264 #endif 1265 PetscFunctionReturn(PETSC_SUCCESS); 1266 } 1267 1268 #if defined(PETSC_USE_DEBUG) 1269 #include <../src/sys/totalview/tv_data_display.h> 1270 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1271 { 1272 TV_add_row("Local rows", "int", &mat->rmap->n); 1273 TV_add_row("Local columns", "int", &mat->cmap->n); 1274 TV_add_row("Global rows", "int", &mat->rmap->N); 1275 TV_add_row("Global columns", "int", &mat->cmap->N); 1276 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1277 return TV_format_OK; 1278 } 1279 #endif 1280 1281 /*@ 1282 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1283 with `MatView()`. The matrix format is determined from the options database. 1284 Generates a parallel MPI matrix if the communicator has more than one 1285 processor. The default matrix type is `MATAIJ`. 1286 1287 Collective 1288 1289 Input Parameters: 1290 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1291 or some related function before a call to `MatLoad()` 1292 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1293 1294 Options Database Key: 1295 . -matload_block_size <bs> - set block size 1296 1297 Level: beginner 1298 1299 Notes: 1300 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1301 `Mat` before calling this routine if you wish to set it from the options database. 1302 1303 `MatLoad()` automatically loads into the options database any options 1304 given in the file filename.info where filename is the name of the file 1305 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1306 file will be ignored if you use the -viewer_binary_skip_info option. 1307 1308 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1309 sets the default matrix type AIJ and sets the local and global sizes. 1310 If type and/or size is already set, then the same are used. 1311 1312 In parallel, each processor can load a subset of rows (or the 1313 entire matrix). This routine is especially useful when a large 1314 matrix is stored on disk and only part of it is desired on each 1315 processor. For example, a parallel solver may access only some of 1316 the rows from each processor. The algorithm used here reads 1317 relatively small blocks of data rather than reading the entire 1318 matrix and then subsetting it. 1319 1320 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1321 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1322 or the sequence like 1323 .vb 1324 `PetscViewer` v; 1325 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1326 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1327 `PetscViewerSetFromOptions`(v); 1328 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1329 `PetscViewerFileSetName`(v,"datafile"); 1330 .ve 1331 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1332 $ -viewer_type {binary, hdf5} 1333 1334 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1335 and src/mat/tutorials/ex10.c with the second approach. 1336 1337 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1338 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1339 Multiple objects, both matrices and vectors, can be stored within the same file. 1340 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1341 1342 Most users should not need to know the details of the binary storage 1343 format, since `MatLoad()` and `MatView()` completely hide these details. 1344 But for anyone who is interested, the standard binary matrix storage 1345 format is 1346 1347 .vb 1348 PetscInt MAT_FILE_CLASSID 1349 PetscInt number of rows 1350 PetscInt number of columns 1351 PetscInt total number of nonzeros 1352 PetscInt *number nonzeros in each row 1353 PetscInt *column indices of all nonzeros (starting index is zero) 1354 PetscScalar *values of all nonzeros 1355 .ve 1356 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1357 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 1358 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1359 1360 PETSc automatically does the byte swapping for 1361 machines that store the bytes reversed. Thus if you write your own binary 1362 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1363 and `PetscBinaryWrite()` to see how this may be done. 1364 1365 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1366 Each processor's chunk is loaded independently by its owning MPI process. 1367 Multiple objects, both matrices and vectors, can be stored within the same file. 1368 They are looked up by their PetscObject name. 1369 1370 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1371 by default the same structure and naming of the AIJ arrays and column count 1372 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1373 $ save example.mat A b -v7.3 1374 can be directly read by this routine (see Reference 1 for details). 1375 1376 Depending on your MATLAB version, this format might be a default, 1377 otherwise you can set it as default in Preferences. 1378 1379 Unless -nocompression flag is used to save the file in MATLAB, 1380 PETSc must be configured with ZLIB package. 1381 1382 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1383 1384 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1385 1386 Corresponding `MatView()` is not yet implemented. 1387 1388 The loaded matrix is actually a transpose of the original one in MATLAB, 1389 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1390 With this format, matrix is automatically transposed by PETSc, 1391 unless the matrix is marked as SPD or symmetric 1392 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1393 1394 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1395 1396 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1397 @*/ 1398 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1399 { 1400 PetscBool flg; 1401 1402 PetscFunctionBegin; 1403 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1404 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1405 1406 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1407 1408 flg = PETSC_FALSE; 1409 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1410 if (flg) { 1411 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1412 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1413 } 1414 flg = PETSC_FALSE; 1415 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1416 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1417 1418 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1419 PetscUseTypeMethod(mat, load, viewer); 1420 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1421 PetscFunctionReturn(PETSC_SUCCESS); 1422 } 1423 1424 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1425 { 1426 Mat_Redundant *redund = *redundant; 1427 1428 PetscFunctionBegin; 1429 if (redund) { 1430 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1431 PetscCall(ISDestroy(&redund->isrow)); 1432 PetscCall(ISDestroy(&redund->iscol)); 1433 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1434 } else { 1435 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1436 PetscCall(PetscFree(redund->sbuf_j)); 1437 PetscCall(PetscFree(redund->sbuf_a)); 1438 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1439 PetscCall(PetscFree(redund->rbuf_j[i])); 1440 PetscCall(PetscFree(redund->rbuf_a[i])); 1441 } 1442 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1443 } 1444 1445 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1446 PetscCall(PetscFree(redund)); 1447 } 1448 PetscFunctionReturn(PETSC_SUCCESS); 1449 } 1450 1451 /*@ 1452 MatDestroy - Frees space taken by a matrix. 1453 1454 Collective 1455 1456 Input Parameter: 1457 . A - the matrix 1458 1459 Level: beginner 1460 1461 Developer Note: 1462 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1463 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1464 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1465 if changes are needed here. 1466 1467 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1468 @*/ 1469 PetscErrorCode MatDestroy(Mat *A) 1470 { 1471 PetscFunctionBegin; 1472 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1473 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1474 if (--((PetscObject)*A)->refct > 0) { 1475 *A = NULL; 1476 PetscFunctionReturn(PETSC_SUCCESS); 1477 } 1478 1479 /* if memory was published with SAWs then destroy it */ 1480 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1481 PetscTryTypeMethod(*A, destroy); 1482 1483 PetscCall(PetscFree((*A)->factorprefix)); 1484 PetscCall(PetscFree((*A)->defaultvectype)); 1485 PetscCall(PetscFree((*A)->defaultrandtype)); 1486 PetscCall(PetscFree((*A)->bsizes)); 1487 PetscCall(PetscFree((*A)->solvertype)); 1488 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1489 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1490 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1491 PetscCall(MatProductClear(*A)); 1492 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1493 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1494 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1495 PetscCall(MatDestroy(&(*A)->schur)); 1496 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1497 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1498 PetscCall(PetscHeaderDestroy(A)); 1499 PetscFunctionReturn(PETSC_SUCCESS); 1500 } 1501 1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1503 /*@ 1504 MatSetValues - Inserts or adds a block of values into a matrix. 1505 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1506 MUST be called after all calls to `MatSetValues()` have been completed. 1507 1508 Not Collective 1509 1510 Input Parameters: 1511 + mat - the matrix 1512 . v - a logically two-dimensional array of values 1513 . m - the number of rows 1514 . idxm - the global indices of the rows 1515 . n - the number of columns 1516 . idxn - the global indices of the columns 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirichlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 Fortran Notes: 1541 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1542 .vb 1543 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1544 .ve 1545 1546 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1547 1548 Developer Note: 1549 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1550 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1551 1552 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1553 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1554 @*/ 1555 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1556 { 1557 PetscFunctionBeginHot; 1558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1559 PetscValidType(mat, 1); 1560 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1561 PetscAssertPointer(idxm, 3); 1562 PetscAssertPointer(idxn, 5); 1563 MatCheckPreallocated(mat, 1); 1564 1565 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1566 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1567 1568 if (PetscDefined(USE_DEBUG)) { 1569 PetscInt i, j; 1570 1571 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1572 if (v) { 1573 for (i = 0; i < m; i++) { 1574 for (j = 0; j < n; j++) { 1575 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1576 #if defined(PETSC_USE_COMPLEX) 1577 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]); 1578 #else 1579 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]); 1580 #endif 1581 } 1582 } 1583 } 1584 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); 1585 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); 1586 } 1587 1588 if (mat->assembled) { 1589 mat->was_assembled = PETSC_TRUE; 1590 mat->assembled = PETSC_FALSE; 1591 } 1592 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1593 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1594 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1595 PetscFunctionReturn(PETSC_SUCCESS); 1596 } 1597 1598 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1599 /*@ 1600 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1601 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1602 MUST be called after all calls to `MatSetValues()` have been completed. 1603 1604 Not Collective 1605 1606 Input Parameters: 1607 + mat - the matrix 1608 . v - a logically two-dimensional array of values 1609 . ism - the rows to provide 1610 . isn - the columns to provide 1611 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1612 1613 Level: beginner 1614 1615 Notes: 1616 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1617 1618 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1619 options cannot be mixed without intervening calls to the assembly 1620 routines. 1621 1622 `MatSetValues()` uses 0-based row and column numbers in Fortran 1623 as well as in C. 1624 1625 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1626 simply ignored. This allows easily inserting element stiffness matrices 1627 with homogeneous Dirichlet boundary conditions that you don't want represented 1628 in the matrix. 1629 1630 Efficiency Alert: 1631 The routine `MatSetValuesBlocked()` may offer much better efficiency 1632 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1633 1634 This is currently not optimized for any particular `ISType` 1635 1636 Developer Note: 1637 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1638 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1639 1640 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1641 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1642 @*/ 1643 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1644 { 1645 PetscInt m, n; 1646 const PetscInt *rows, *cols; 1647 1648 PetscFunctionBeginHot; 1649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1650 PetscCall(ISGetIndices(ism, &rows)); 1651 PetscCall(ISGetIndices(isn, &cols)); 1652 PetscCall(ISGetLocalSize(ism, &m)); 1653 PetscCall(ISGetLocalSize(isn, &n)); 1654 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1655 PetscCall(ISRestoreIndices(ism, &rows)); 1656 PetscCall(ISRestoreIndices(isn, &cols)); 1657 PetscFunctionReturn(PETSC_SUCCESS); 1658 } 1659 1660 /*@ 1661 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1662 values into a matrix 1663 1664 Not Collective 1665 1666 Input Parameters: 1667 + mat - the matrix 1668 . row - the (block) row to set 1669 - v - a logically two-dimensional array of values 1670 1671 Level: intermediate 1672 1673 Notes: 1674 The values, `v`, are column-oriented (for the block version) and sorted 1675 1676 All the nonzero values in `row` must be provided 1677 1678 The matrix must have previously had its column indices set, likely by having been assembled. 1679 1680 `row` must belong to this MPI process 1681 1682 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1683 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1684 @*/ 1685 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1686 { 1687 PetscInt globalrow; 1688 1689 PetscFunctionBegin; 1690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1691 PetscValidType(mat, 1); 1692 PetscAssertPointer(v, 3); 1693 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1694 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1695 PetscFunctionReturn(PETSC_SUCCESS); 1696 } 1697 1698 /*@ 1699 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1700 values into a matrix 1701 1702 Not Collective 1703 1704 Input Parameters: 1705 + mat - the matrix 1706 . row - the (block) row to set 1707 - 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 1708 1709 Level: advanced 1710 1711 Notes: 1712 The values, `v`, are column-oriented for the block version. 1713 1714 All the nonzeros in `row` must be provided 1715 1716 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1717 1718 `row` must belong to this process 1719 1720 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1721 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1722 @*/ 1723 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1724 { 1725 PetscFunctionBeginHot; 1726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1727 PetscValidType(mat, 1); 1728 MatCheckPreallocated(mat, 1); 1729 PetscAssertPointer(v, 3); 1730 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1731 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1732 mat->insertmode = INSERT_VALUES; 1733 1734 if (mat->assembled) { 1735 mat->was_assembled = PETSC_TRUE; 1736 mat->assembled = PETSC_FALSE; 1737 } 1738 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1739 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1740 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1741 PetscFunctionReturn(PETSC_SUCCESS); 1742 } 1743 1744 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1745 /*@ 1746 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1747 Using structured grid indexing 1748 1749 Not Collective 1750 1751 Input Parameters: 1752 + mat - the matrix 1753 . m - number of rows being entered 1754 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1755 . n - number of columns being entered 1756 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1757 . v - a logically two-dimensional array of values 1758 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1759 1760 Level: beginner 1761 1762 Notes: 1763 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1764 1765 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1766 options cannot be mixed without intervening calls to the assembly 1767 routines. 1768 1769 The grid coordinates are across the entire grid, not just the local portion 1770 1771 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1772 as well as in C. 1773 1774 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1775 1776 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1777 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1778 1779 The columns and rows in the stencil passed in MUST be contained within the 1780 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1781 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1782 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1783 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1784 1785 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1786 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1787 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1788 `DM_BOUNDARY_PERIODIC` boundary type. 1789 1790 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 1791 a single value per point) you can skip filling those indices. 1792 1793 Inspired by the structured grid interface to the HYPRE package 1794 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1795 1796 Efficiency Alert: 1797 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1798 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1799 1800 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1801 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1802 @*/ 1803 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1804 { 1805 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1806 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1807 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1808 1809 PetscFunctionBegin; 1810 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1812 PetscValidType(mat, 1); 1813 PetscAssertPointer(idxm, 3); 1814 PetscAssertPointer(idxn, 5); 1815 1816 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1817 jdxm = buf; 1818 jdxn = buf + m; 1819 } else { 1820 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1821 jdxm = bufm; 1822 jdxn = bufn; 1823 } 1824 for (i = 0; i < m; i++) { 1825 for (j = 0; j < 3 - sdim; j++) dxm++; 1826 tmp = *dxm++ - starts[0]; 1827 for (j = 0; j < dim - 1; j++) { 1828 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1829 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1830 } 1831 if (mat->stencil.noc) dxm++; 1832 jdxm[i] = tmp; 1833 } 1834 for (i = 0; i < n; i++) { 1835 for (j = 0; j < 3 - sdim; j++) dxn++; 1836 tmp = *dxn++ - starts[0]; 1837 for (j = 0; j < dim - 1; j++) { 1838 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1839 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1840 } 1841 if (mat->stencil.noc) dxn++; 1842 jdxn[i] = tmp; 1843 } 1844 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1845 PetscCall(PetscFree2(bufm, bufn)); 1846 PetscFunctionReturn(PETSC_SUCCESS); 1847 } 1848 1849 /*@ 1850 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1851 Using structured grid indexing 1852 1853 Not Collective 1854 1855 Input Parameters: 1856 + mat - the matrix 1857 . m - number of rows being entered 1858 . idxm - grid coordinates for matrix rows being entered 1859 . n - number of columns being entered 1860 . idxn - grid coordinates for matrix columns being entered 1861 . v - a logically two-dimensional array of values 1862 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1863 1864 Level: beginner 1865 1866 Notes: 1867 By default the values, `v`, are row-oriented and unsorted. 1868 See `MatSetOption()` for other options. 1869 1870 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1871 options cannot be mixed without intervening calls to the assembly 1872 routines. 1873 1874 The grid coordinates are across the entire grid, not just the local portion 1875 1876 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1877 as well as in C. 1878 1879 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1880 1881 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1882 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1883 1884 The columns and rows in the stencil passed in MUST be contained within the 1885 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1886 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1887 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1888 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1889 1890 Negative indices may be passed in idxm and idxn, these rows and columns are 1891 simply ignored. This allows easily inserting element stiffness matrices 1892 with homogeneous Dirichlet boundary conditions that you don't want represented 1893 in the matrix. 1894 1895 Inspired by the structured grid interface to the HYPRE package 1896 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1897 1898 Fortran Note: 1899 `idxm` and `idxn` should be declared as 1900 $ MatStencil idxm(4,m),idxn(4,n) 1901 and the values inserted using 1902 .vb 1903 idxm(MatStencil_i,1) = i 1904 idxm(MatStencil_j,1) = j 1905 idxm(MatStencil_k,1) = k 1906 etc 1907 .ve 1908 1909 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1910 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1911 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1912 @*/ 1913 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1914 { 1915 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1916 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1917 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1918 1919 PetscFunctionBegin; 1920 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1922 PetscValidType(mat, 1); 1923 PetscAssertPointer(idxm, 3); 1924 PetscAssertPointer(idxn, 5); 1925 PetscAssertPointer(v, 6); 1926 1927 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1928 jdxm = buf; 1929 jdxn = buf + m; 1930 } else { 1931 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1932 jdxm = bufm; 1933 jdxn = bufn; 1934 } 1935 for (i = 0; i < m; i++) { 1936 for (j = 0; j < 3 - sdim; j++) dxm++; 1937 tmp = *dxm++ - starts[0]; 1938 for (j = 0; j < sdim - 1; j++) { 1939 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1940 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1941 } 1942 dxm++; 1943 jdxm[i] = tmp; 1944 } 1945 for (i = 0; i < n; i++) { 1946 for (j = 0; j < 3 - sdim; j++) dxn++; 1947 tmp = *dxn++ - starts[0]; 1948 for (j = 0; j < sdim - 1; j++) { 1949 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1950 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1951 } 1952 dxn++; 1953 jdxn[i] = tmp; 1954 } 1955 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1956 PetscCall(PetscFree2(bufm, bufn)); 1957 PetscFunctionReturn(PETSC_SUCCESS); 1958 } 1959 1960 /*@ 1961 MatSetStencil - Sets the grid information for setting values into a matrix via 1962 `MatSetValuesStencil()` 1963 1964 Not Collective 1965 1966 Input Parameters: 1967 + mat - the matrix 1968 . dim - dimension of the grid 1, 2, or 3 1969 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1970 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1971 - dof - number of degrees of freedom per node 1972 1973 Level: beginner 1974 1975 Notes: 1976 Inspired by the structured grid interface to the HYPRE package 1977 (www.llnl.gov/CASC/hyper) 1978 1979 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1980 user. 1981 1982 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1983 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1984 @*/ 1985 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1986 { 1987 PetscFunctionBegin; 1988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1989 PetscAssertPointer(dims, 3); 1990 PetscAssertPointer(starts, 4); 1991 1992 mat->stencil.dim = dim + (dof > 1); 1993 for (PetscInt i = 0; i < dim; i++) { 1994 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1995 mat->stencil.starts[i] = starts[dim - i - 1]; 1996 } 1997 mat->stencil.dims[dim] = dof; 1998 mat->stencil.starts[dim] = 0; 1999 mat->stencil.noc = (PetscBool)(dof == 1); 2000 PetscFunctionReturn(PETSC_SUCCESS); 2001 } 2002 2003 /*@ 2004 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2005 2006 Not Collective 2007 2008 Input Parameters: 2009 + mat - the matrix 2010 . v - a logically two-dimensional array of values 2011 . m - the number of block rows 2012 . idxm - the global block indices 2013 . n - the number of block columns 2014 . idxn - the global block indices 2015 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2016 2017 Level: intermediate 2018 2019 Notes: 2020 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2021 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2022 2023 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2024 NOT the total number of rows/columns; for example, if the block size is 2 and 2025 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2026 The values in `idxm` would be 1 2; that is the first index for each block divided by 2027 the block size. 2028 2029 You must call `MatSetBlockSize()` when constructing this matrix (before 2030 preallocating it). 2031 2032 By default the values, `v`, are row-oriented, so the layout of 2033 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2034 2035 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2036 options cannot be mixed without intervening calls to the assembly 2037 routines. 2038 2039 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2040 as well as in C. 2041 2042 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2043 simply ignored. This allows easily inserting element stiffness matrices 2044 with homogeneous Dirichlet boundary conditions that you don't want represented 2045 in the matrix. 2046 2047 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2048 internal searching must be done to determine where to place the 2049 data in the matrix storage space. By instead inserting blocks of 2050 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2051 reduced. 2052 2053 Example: 2054 .vb 2055 Suppose m=n=2 and block size(bs) = 2 The array is 2056 2057 1 2 | 3 4 2058 5 6 | 7 8 2059 - - - | - - - 2060 9 10 | 11 12 2061 13 14 | 15 16 2062 2063 v[] should be passed in like 2064 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2065 2066 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2067 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2068 .ve 2069 2070 Fortran Notes: 2071 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2072 .vb 2073 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2074 .ve 2075 2076 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2077 2078 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2079 @*/ 2080 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2081 { 2082 PetscFunctionBeginHot; 2083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2084 PetscValidType(mat, 1); 2085 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2086 PetscAssertPointer(idxm, 3); 2087 PetscAssertPointer(idxn, 5); 2088 MatCheckPreallocated(mat, 1); 2089 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2090 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2091 if (PetscDefined(USE_DEBUG)) { 2092 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2093 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2094 } 2095 if (PetscDefined(USE_DEBUG)) { 2096 PetscInt rbs, cbs, M, N, i; 2097 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2098 PetscCall(MatGetSize(mat, &M, &N)); 2099 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); 2100 for (i = 0; i < n; i++) 2101 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); 2102 } 2103 if (mat->assembled) { 2104 mat->was_assembled = PETSC_TRUE; 2105 mat->assembled = PETSC_FALSE; 2106 } 2107 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2108 if (mat->ops->setvaluesblocked) { 2109 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2110 } else { 2111 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2112 PetscInt i, j, bs, cbs; 2113 2114 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2115 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2116 iidxm = buf; 2117 iidxn = buf + m * bs; 2118 } else { 2119 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2120 iidxm = bufr; 2121 iidxn = bufc; 2122 } 2123 for (i = 0; i < m; i++) { 2124 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2125 } 2126 if (m != n || bs != cbs || idxm != idxn) { 2127 for (i = 0; i < n; i++) { 2128 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2129 } 2130 } else iidxn = iidxm; 2131 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2132 PetscCall(PetscFree2(bufr, bufc)); 2133 } 2134 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2135 PetscFunctionReturn(PETSC_SUCCESS); 2136 } 2137 2138 /*@ 2139 MatGetValues - Gets a block of local values from a matrix. 2140 2141 Not Collective; can only return values that are owned by the give process 2142 2143 Input Parameters: 2144 + mat - the matrix 2145 . v - a logically two-dimensional array for storing the values 2146 . m - the number of rows 2147 . idxm - the global indices of the rows 2148 . n - the number of columns 2149 - idxn - the global indices of the columns 2150 2151 Level: advanced 2152 2153 Notes: 2154 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2155 The values, `v`, are then returned in a row-oriented format, 2156 analogous to that used by default in `MatSetValues()`. 2157 2158 `MatGetValues()` uses 0-based row and column numbers in 2159 Fortran as well as in C. 2160 2161 `MatGetValues()` requires that the matrix has been assembled 2162 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2163 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2164 without intermediate matrix assembly. 2165 2166 Negative row or column indices will be ignored and those locations in `v` will be 2167 left unchanged. 2168 2169 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2170 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2171 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2172 2173 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2174 @*/ 2175 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2176 { 2177 PetscFunctionBegin; 2178 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2179 PetscValidType(mat, 1); 2180 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2181 PetscAssertPointer(idxm, 3); 2182 PetscAssertPointer(idxn, 5); 2183 PetscAssertPointer(v, 6); 2184 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2185 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2186 MatCheckPreallocated(mat, 1); 2187 2188 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2189 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2190 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2191 PetscFunctionReturn(PETSC_SUCCESS); 2192 } 2193 2194 /*@ 2195 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2196 defined previously by `MatSetLocalToGlobalMapping()` 2197 2198 Not Collective 2199 2200 Input Parameters: 2201 + mat - the matrix 2202 . nrow - number of rows 2203 . irow - the row local indices 2204 . ncol - number of columns 2205 - icol - the column local indices 2206 2207 Output Parameter: 2208 . y - a logically two-dimensional array of values 2209 2210 Level: advanced 2211 2212 Notes: 2213 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2214 2215 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, 2216 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2217 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2218 with `MatSetLocalToGlobalMapping()`. 2219 2220 Developer Note: 2221 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2222 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2223 2224 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2225 `MatSetValuesLocal()`, `MatGetValues()` 2226 @*/ 2227 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2228 { 2229 PetscFunctionBeginHot; 2230 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2231 PetscValidType(mat, 1); 2232 MatCheckPreallocated(mat, 1); 2233 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2234 PetscAssertPointer(irow, 3); 2235 PetscAssertPointer(icol, 5); 2236 if (PetscDefined(USE_DEBUG)) { 2237 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2238 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2239 } 2240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2241 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2242 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2243 else { 2244 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2245 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2246 irowm = buf; 2247 icolm = buf + nrow; 2248 } else { 2249 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2250 irowm = bufr; 2251 icolm = bufc; 2252 } 2253 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2254 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2255 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2256 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2257 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2258 PetscCall(PetscFree2(bufr, bufc)); 2259 } 2260 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2261 PetscFunctionReturn(PETSC_SUCCESS); 2262 } 2263 2264 /*@ 2265 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2266 the same size. Currently, this can only be called once and creates the given matrix. 2267 2268 Not Collective 2269 2270 Input Parameters: 2271 + mat - the matrix 2272 . nb - the number of blocks 2273 . bs - the number of rows (and columns) in each block 2274 . rows - a concatenation of the rows for each block 2275 - v - a concatenation of logically two-dimensional arrays of values 2276 2277 Level: advanced 2278 2279 Notes: 2280 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2281 2282 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2283 2284 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2285 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2286 @*/ 2287 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2288 { 2289 PetscFunctionBegin; 2290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2291 PetscValidType(mat, 1); 2292 PetscAssertPointer(rows, 4); 2293 PetscAssertPointer(v, 5); 2294 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2295 2296 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2297 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2298 else { 2299 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2300 } 2301 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2302 PetscFunctionReturn(PETSC_SUCCESS); 2303 } 2304 2305 /*@ 2306 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2307 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2308 using a local (per-processor) numbering. 2309 2310 Not Collective 2311 2312 Input Parameters: 2313 + x - the matrix 2314 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2315 - cmapping - column mapping 2316 2317 Level: intermediate 2318 2319 Note: 2320 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2321 2322 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2323 @*/ 2324 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2325 { 2326 PetscFunctionBegin; 2327 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2328 PetscValidType(x, 1); 2329 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2330 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2331 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2332 else { 2333 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2334 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2335 } 2336 PetscFunctionReturn(PETSC_SUCCESS); 2337 } 2338 2339 /*@ 2340 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2341 2342 Not Collective 2343 2344 Input Parameter: 2345 . A - the matrix 2346 2347 Output Parameters: 2348 + rmapping - row mapping 2349 - cmapping - column mapping 2350 2351 Level: advanced 2352 2353 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2354 @*/ 2355 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2356 { 2357 PetscFunctionBegin; 2358 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2359 PetscValidType(A, 1); 2360 if (rmapping) { 2361 PetscAssertPointer(rmapping, 2); 2362 *rmapping = A->rmap->mapping; 2363 } 2364 if (cmapping) { 2365 PetscAssertPointer(cmapping, 3); 2366 *cmapping = A->cmap->mapping; 2367 } 2368 PetscFunctionReturn(PETSC_SUCCESS); 2369 } 2370 2371 /*@ 2372 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2373 2374 Logically Collective 2375 2376 Input Parameters: 2377 + A - the matrix 2378 . rmap - row layout 2379 - cmap - column layout 2380 2381 Level: advanced 2382 2383 Note: 2384 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2385 2386 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2387 @*/ 2388 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2389 { 2390 PetscFunctionBegin; 2391 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2392 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2393 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2394 PetscFunctionReturn(PETSC_SUCCESS); 2395 } 2396 2397 /*@ 2398 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2399 2400 Not Collective 2401 2402 Input Parameter: 2403 . A - the matrix 2404 2405 Output Parameters: 2406 + rmap - row layout 2407 - cmap - column layout 2408 2409 Level: advanced 2410 2411 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2412 @*/ 2413 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2414 { 2415 PetscFunctionBegin; 2416 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2417 PetscValidType(A, 1); 2418 if (rmap) { 2419 PetscAssertPointer(rmap, 2); 2420 *rmap = A->rmap; 2421 } 2422 if (cmap) { 2423 PetscAssertPointer(cmap, 3); 2424 *cmap = A->cmap; 2425 } 2426 PetscFunctionReturn(PETSC_SUCCESS); 2427 } 2428 2429 /*@ 2430 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2431 using a local numbering of the rows and columns. 2432 2433 Not Collective 2434 2435 Input Parameters: 2436 + mat - the matrix 2437 . nrow - number of rows 2438 . irow - the row local indices 2439 . ncol - number of columns 2440 . icol - the column local indices 2441 . y - a logically two-dimensional array of values 2442 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2443 2444 Level: intermediate 2445 2446 Notes: 2447 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2448 2449 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2450 options cannot be mixed without intervening calls to the assembly 2451 routines. 2452 2453 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2454 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2455 2456 Fortran Notes: 2457 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2458 .vb 2459 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2460 .ve 2461 2462 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2463 2464 Developer Note: 2465 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2466 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2467 2468 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2469 `MatGetValuesLocal()` 2470 @*/ 2471 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2472 { 2473 PetscFunctionBeginHot; 2474 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2475 PetscValidType(mat, 1); 2476 MatCheckPreallocated(mat, 1); 2477 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2478 PetscAssertPointer(irow, 3); 2479 PetscAssertPointer(icol, 5); 2480 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2481 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2482 if (PetscDefined(USE_DEBUG)) { 2483 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2484 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2485 } 2486 2487 if (mat->assembled) { 2488 mat->was_assembled = PETSC_TRUE; 2489 mat->assembled = PETSC_FALSE; 2490 } 2491 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2492 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2493 else { 2494 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2495 const PetscInt *irowm, *icolm; 2496 2497 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2498 bufr = buf; 2499 bufc = buf + nrow; 2500 irowm = bufr; 2501 icolm = bufc; 2502 } else { 2503 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2504 irowm = bufr; 2505 icolm = bufc; 2506 } 2507 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2508 else irowm = irow; 2509 if (mat->cmap->mapping) { 2510 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2511 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2512 } else icolm = irowm; 2513 } else icolm = icol; 2514 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2515 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2516 } 2517 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2518 PetscFunctionReturn(PETSC_SUCCESS); 2519 } 2520 2521 /*@ 2522 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2523 using a local ordering of the nodes a block at a time. 2524 2525 Not Collective 2526 2527 Input Parameters: 2528 + mat - the matrix 2529 . nrow - number of rows 2530 . irow - the row local indices 2531 . ncol - number of columns 2532 . icol - the column local indices 2533 . y - a logically two-dimensional array of values 2534 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2535 2536 Level: intermediate 2537 2538 Notes: 2539 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2540 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2541 2542 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2543 options cannot be mixed without intervening calls to the assembly 2544 routines. 2545 2546 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2547 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2548 2549 Fortran Notes: 2550 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2551 .vb 2552 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2553 .ve 2554 2555 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2556 2557 Developer Note: 2558 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2559 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2560 2561 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2562 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2563 @*/ 2564 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2565 { 2566 PetscFunctionBeginHot; 2567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2568 PetscValidType(mat, 1); 2569 MatCheckPreallocated(mat, 1); 2570 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2571 PetscAssertPointer(irow, 3); 2572 PetscAssertPointer(icol, 5); 2573 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2574 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2575 if (PetscDefined(USE_DEBUG)) { 2576 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2577 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); 2578 } 2579 2580 if (mat->assembled) { 2581 mat->was_assembled = PETSC_TRUE; 2582 mat->assembled = PETSC_FALSE; 2583 } 2584 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2585 PetscInt irbs, rbs; 2586 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2587 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2588 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2589 } 2590 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2591 PetscInt icbs, cbs; 2592 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2593 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2594 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2595 } 2596 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2597 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2598 else { 2599 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2600 const PetscInt *irowm, *icolm; 2601 2602 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2603 bufr = buf; 2604 bufc = buf + nrow; 2605 irowm = bufr; 2606 icolm = bufc; 2607 } else { 2608 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2609 irowm = bufr; 2610 icolm = bufc; 2611 } 2612 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2613 else irowm = irow; 2614 if (mat->cmap->mapping) { 2615 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2616 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2617 } else icolm = irowm; 2618 } else icolm = icol; 2619 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2620 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2621 } 2622 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2623 PetscFunctionReturn(PETSC_SUCCESS); 2624 } 2625 2626 /*@ 2627 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2628 2629 Collective 2630 2631 Input Parameters: 2632 + mat - the matrix 2633 - x - the vector to be multiplied 2634 2635 Output Parameter: 2636 . y - the result 2637 2638 Level: developer 2639 2640 Note: 2641 The vectors `x` and `y` cannot be the same. I.e., one cannot 2642 call `MatMultDiagonalBlock`(A,y,y). 2643 2644 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2645 @*/ 2646 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2647 { 2648 PetscFunctionBegin; 2649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2650 PetscValidType(mat, 1); 2651 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2652 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2653 2654 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2655 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2656 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2657 MatCheckPreallocated(mat, 1); 2658 2659 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2660 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2661 PetscFunctionReturn(PETSC_SUCCESS); 2662 } 2663 2664 /*@ 2665 MatMult - Computes the matrix-vector product, $y = Ax$. 2666 2667 Neighbor-wise Collective 2668 2669 Input Parameters: 2670 + mat - the matrix 2671 - x - the vector to be multiplied 2672 2673 Output Parameter: 2674 . y - the result 2675 2676 Level: beginner 2677 2678 Note: 2679 The vectors `x` and `y` cannot be the same. I.e., one cannot 2680 call `MatMult`(A,y,y). 2681 2682 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2683 @*/ 2684 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2685 { 2686 PetscFunctionBegin; 2687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2688 PetscValidType(mat, 1); 2689 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2690 VecCheckAssembled(x); 2691 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2692 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2693 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2694 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2695 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); 2696 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); 2697 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); 2698 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); 2699 PetscCall(VecSetErrorIfLocked(y, 3)); 2700 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2701 MatCheckPreallocated(mat, 1); 2702 2703 PetscCall(VecLockReadPush(x)); 2704 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2705 PetscUseTypeMethod(mat, mult, x, y); 2706 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2707 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2708 PetscCall(VecLockReadPop(x)); 2709 PetscFunctionReturn(PETSC_SUCCESS); 2710 } 2711 2712 /*@ 2713 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2714 2715 Neighbor-wise Collective 2716 2717 Input Parameters: 2718 + mat - the matrix 2719 - x - the vector to be multiplied 2720 2721 Output Parameter: 2722 . y - the result 2723 2724 Level: beginner 2725 2726 Notes: 2727 The vectors `x` and `y` cannot be the same. I.e., one cannot 2728 call `MatMultTranspose`(A,y,y). 2729 2730 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2731 use `MatMultHermitianTranspose()` 2732 2733 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2734 @*/ 2735 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2736 { 2737 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2738 2739 PetscFunctionBegin; 2740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2741 PetscValidType(mat, 1); 2742 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2743 VecCheckAssembled(x); 2744 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2745 2746 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2747 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2748 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2749 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); 2750 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); 2751 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); 2752 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); 2753 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2754 MatCheckPreallocated(mat, 1); 2755 2756 if (!mat->ops->multtranspose) { 2757 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2758 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); 2759 } else op = mat->ops->multtranspose; 2760 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2761 PetscCall(VecLockReadPush(x)); 2762 PetscCall((*op)(mat, x, y)); 2763 PetscCall(VecLockReadPop(x)); 2764 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2765 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2766 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2767 PetscFunctionReturn(PETSC_SUCCESS); 2768 } 2769 2770 /*@ 2771 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2772 2773 Neighbor-wise Collective 2774 2775 Input Parameters: 2776 + mat - the matrix 2777 - x - the vector to be multiplied 2778 2779 Output Parameter: 2780 . y - the result 2781 2782 Level: beginner 2783 2784 Notes: 2785 The vectors `x` and `y` cannot be the same. I.e., one cannot 2786 call `MatMultHermitianTranspose`(A,y,y). 2787 2788 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2789 2790 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2791 2792 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2793 @*/ 2794 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2795 { 2796 PetscFunctionBegin; 2797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2798 PetscValidType(mat, 1); 2799 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2800 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2801 2802 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2803 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2804 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2805 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); 2806 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); 2807 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); 2808 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); 2809 MatCheckPreallocated(mat, 1); 2810 2811 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2812 #if defined(PETSC_USE_COMPLEX) 2813 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2814 PetscCall(VecLockReadPush(x)); 2815 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2816 else PetscUseTypeMethod(mat, mult, x, y); 2817 PetscCall(VecLockReadPop(x)); 2818 } else { 2819 Vec w; 2820 PetscCall(VecDuplicate(x, &w)); 2821 PetscCall(VecCopy(x, w)); 2822 PetscCall(VecConjugate(w)); 2823 PetscCall(MatMultTranspose(mat, w, y)); 2824 PetscCall(VecDestroy(&w)); 2825 PetscCall(VecConjugate(y)); 2826 } 2827 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2828 #else 2829 PetscCall(MatMultTranspose(mat, x, y)); 2830 #endif 2831 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2832 PetscFunctionReturn(PETSC_SUCCESS); 2833 } 2834 2835 /*@ 2836 MatMultAdd - Computes $v3 = v2 + A * v1$. 2837 2838 Neighbor-wise Collective 2839 2840 Input Parameters: 2841 + mat - the matrix 2842 . v1 - the vector to be multiplied by `mat` 2843 - v2 - the vector to be added to the result 2844 2845 Output Parameter: 2846 . v3 - the result 2847 2848 Level: beginner 2849 2850 Note: 2851 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2852 call `MatMultAdd`(A,v1,v2,v1). 2853 2854 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2855 @*/ 2856 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2857 { 2858 PetscFunctionBegin; 2859 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2860 PetscValidType(mat, 1); 2861 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2862 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2863 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2864 2865 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2866 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2867 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); 2868 /* 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); 2869 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); */ 2870 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); 2871 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); 2872 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2873 MatCheckPreallocated(mat, 1); 2874 2875 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2876 PetscCall(VecLockReadPush(v1)); 2877 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2878 PetscCall(VecLockReadPop(v1)); 2879 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2880 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2881 PetscFunctionReturn(PETSC_SUCCESS); 2882 } 2883 2884 /*@ 2885 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2886 2887 Neighbor-wise Collective 2888 2889 Input Parameters: 2890 + mat - the matrix 2891 . v1 - the vector to be multiplied by the transpose of the matrix 2892 - v2 - the vector to be added to the result 2893 2894 Output Parameter: 2895 . v3 - the result 2896 2897 Level: beginner 2898 2899 Note: 2900 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2901 call `MatMultTransposeAdd`(A,v1,v2,v1). 2902 2903 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2904 @*/ 2905 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2906 { 2907 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2908 2909 PetscFunctionBegin; 2910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2911 PetscValidType(mat, 1); 2912 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2913 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2914 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2915 2916 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2917 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2918 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); 2919 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); 2920 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); 2921 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2922 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2923 MatCheckPreallocated(mat, 1); 2924 2925 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2926 PetscCall(VecLockReadPush(v1)); 2927 PetscCall((*op)(mat, v1, v2, v3)); 2928 PetscCall(VecLockReadPop(v1)); 2929 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2930 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2931 PetscFunctionReturn(PETSC_SUCCESS); 2932 } 2933 2934 /*@ 2935 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2936 2937 Neighbor-wise Collective 2938 2939 Input Parameters: 2940 + mat - the matrix 2941 . v1 - the vector to be multiplied by the Hermitian transpose 2942 - v2 - the vector to be added to the result 2943 2944 Output Parameter: 2945 . v3 - the result 2946 2947 Level: beginner 2948 2949 Note: 2950 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2951 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2952 2953 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2954 @*/ 2955 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2956 { 2957 PetscFunctionBegin; 2958 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2959 PetscValidType(mat, 1); 2960 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2961 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2962 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2963 2964 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2965 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2966 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2967 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); 2968 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); 2969 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); 2970 MatCheckPreallocated(mat, 1); 2971 2972 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2973 PetscCall(VecLockReadPush(v1)); 2974 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2975 else { 2976 Vec w, z; 2977 PetscCall(VecDuplicate(v1, &w)); 2978 PetscCall(VecCopy(v1, w)); 2979 PetscCall(VecConjugate(w)); 2980 PetscCall(VecDuplicate(v3, &z)); 2981 PetscCall(MatMultTranspose(mat, w, z)); 2982 PetscCall(VecDestroy(&w)); 2983 PetscCall(VecConjugate(z)); 2984 if (v2 != v3) { 2985 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2986 } else { 2987 PetscCall(VecAXPY(v3, 1.0, z)); 2988 } 2989 PetscCall(VecDestroy(&z)); 2990 } 2991 PetscCall(VecLockReadPop(v1)); 2992 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2993 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2994 PetscFunctionReturn(PETSC_SUCCESS); 2995 } 2996 2997 /*@ 2998 MatGetFactorType - gets the type of factorization a matrix is 2999 3000 Not Collective 3001 3002 Input Parameter: 3003 . mat - the matrix 3004 3005 Output Parameter: 3006 . 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` 3007 3008 Level: intermediate 3009 3010 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3011 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3012 @*/ 3013 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3014 { 3015 PetscFunctionBegin; 3016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3017 PetscValidType(mat, 1); 3018 PetscAssertPointer(t, 2); 3019 *t = mat->factortype; 3020 PetscFunctionReturn(PETSC_SUCCESS); 3021 } 3022 3023 /*@ 3024 MatSetFactorType - sets the type of factorization a matrix is 3025 3026 Logically Collective 3027 3028 Input Parameters: 3029 + mat - the matrix 3030 - 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` 3031 3032 Level: intermediate 3033 3034 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3035 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3036 @*/ 3037 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3038 { 3039 PetscFunctionBegin; 3040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3041 PetscValidType(mat, 1); 3042 mat->factortype = t; 3043 PetscFunctionReturn(PETSC_SUCCESS); 3044 } 3045 3046 /*@ 3047 MatGetInfo - Returns information about matrix storage (number of 3048 nonzeros, memory, etc.). 3049 3050 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3051 3052 Input Parameters: 3053 + mat - the matrix 3054 - 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) 3055 3056 Output Parameter: 3057 . info - matrix information context 3058 3059 Options Database Key: 3060 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3061 3062 Level: intermediate 3063 3064 Notes: 3065 The `MatInfo` context contains a variety of matrix data, including 3066 number of nonzeros allocated and used, number of mallocs during 3067 matrix assembly, etc. Additional information for factored matrices 3068 is provided (such as the fill ratio, number of mallocs during 3069 factorization, etc.). 3070 3071 Example: 3072 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3073 data within the `MatInfo` context. For example, 3074 .vb 3075 MatInfo info; 3076 Mat A; 3077 double mal, nz_a, nz_u; 3078 3079 MatGetInfo(A, MAT_LOCAL, &info); 3080 mal = info.mallocs; 3081 nz_a = info.nz_allocated; 3082 .ve 3083 3084 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3085 @*/ 3086 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3087 { 3088 PetscFunctionBegin; 3089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3090 PetscValidType(mat, 1); 3091 PetscAssertPointer(info, 3); 3092 MatCheckPreallocated(mat, 1); 3093 PetscUseTypeMethod(mat, getinfo, flag, info); 3094 PetscFunctionReturn(PETSC_SUCCESS); 3095 } 3096 3097 /* 3098 This is used by external packages where it is not easy to get the info from the actual 3099 matrix factorization. 3100 */ 3101 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3102 { 3103 PetscFunctionBegin; 3104 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3105 PetscFunctionReturn(PETSC_SUCCESS); 3106 } 3107 3108 /*@ 3109 MatLUFactor - Performs in-place LU factorization of matrix. 3110 3111 Collective 3112 3113 Input Parameters: 3114 + mat - the matrix 3115 . row - row permutation 3116 . col - column permutation 3117 - info - options for factorization, includes 3118 .vb 3119 fill - expected fill as ratio of original fill. 3120 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3121 Run with the option -info to determine an optimal value to use 3122 .ve 3123 3124 Level: developer 3125 3126 Notes: 3127 Most users should employ the `KSP` interface for linear solvers 3128 instead of working directly with matrix algebra routines such as this. 3129 See, e.g., `KSPCreate()`. 3130 3131 This changes the state of the matrix to a factored matrix; it cannot be used 3132 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3133 3134 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3135 when not using `KSP`. 3136 3137 Developer Note: 3138 The Fortran interface is not autogenerated as the 3139 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3140 3141 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3142 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3143 @*/ 3144 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3145 { 3146 MatFactorInfo tinfo; 3147 3148 PetscFunctionBegin; 3149 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3150 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3151 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3152 if (info) PetscAssertPointer(info, 4); 3153 PetscValidType(mat, 1); 3154 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3155 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3156 MatCheckPreallocated(mat, 1); 3157 if (!info) { 3158 PetscCall(MatFactorInfoInitialize(&tinfo)); 3159 info = &tinfo; 3160 } 3161 3162 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3163 PetscUseTypeMethod(mat, lufactor, row, col, info); 3164 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3165 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3166 PetscFunctionReturn(PETSC_SUCCESS); 3167 } 3168 3169 /*@ 3170 MatILUFactor - Performs in-place ILU factorization of matrix. 3171 3172 Collective 3173 3174 Input Parameters: 3175 + mat - the matrix 3176 . row - row permutation 3177 . col - column permutation 3178 - info - structure containing 3179 .vb 3180 levels - number of levels of fill. 3181 expected fill - as ratio of original fill. 3182 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3183 missing diagonal entries) 3184 .ve 3185 3186 Level: developer 3187 3188 Notes: 3189 Most users should employ the `KSP` interface for linear solvers 3190 instead of working directly with matrix algebra routines such as this. 3191 See, e.g., `KSPCreate()`. 3192 3193 Probably really in-place only when level of fill is zero, otherwise allocates 3194 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3195 when not using `KSP`. 3196 3197 Developer Note: 3198 The Fortran interface is not autogenerated as the 3199 interface definition cannot be generated correctly [due to MatFactorInfo] 3200 3201 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3202 @*/ 3203 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3204 { 3205 PetscFunctionBegin; 3206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3207 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3208 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3209 PetscAssertPointer(info, 4); 3210 PetscValidType(mat, 1); 3211 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3212 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3213 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3214 MatCheckPreallocated(mat, 1); 3215 3216 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3217 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3218 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3219 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3220 PetscFunctionReturn(PETSC_SUCCESS); 3221 } 3222 3223 /*@ 3224 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3225 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3226 3227 Collective 3228 3229 Input Parameters: 3230 + fact - the factor matrix obtained with `MatGetFactor()` 3231 . mat - the matrix 3232 . row - the row permutation 3233 . col - the column permutation 3234 - info - options for factorization, includes 3235 .vb 3236 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3237 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3238 .ve 3239 3240 Level: developer 3241 3242 Notes: 3243 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3244 3245 Most users should employ the simplified `KSP` interface for linear solvers 3246 instead of working directly with matrix algebra routines such as this. 3247 See, e.g., `KSPCreate()`. 3248 3249 Developer Note: 3250 The Fortran interface is not autogenerated as the 3251 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3252 3253 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3254 @*/ 3255 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3256 { 3257 MatFactorInfo tinfo; 3258 3259 PetscFunctionBegin; 3260 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3261 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3262 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3263 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3264 if (info) PetscAssertPointer(info, 5); 3265 PetscValidType(fact, 1); 3266 PetscValidType(mat, 2); 3267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3268 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3269 MatCheckPreallocated(mat, 2); 3270 if (!info) { 3271 PetscCall(MatFactorInfoInitialize(&tinfo)); 3272 info = &tinfo; 3273 } 3274 3275 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3276 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3277 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3278 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3279 PetscFunctionReturn(PETSC_SUCCESS); 3280 } 3281 3282 /*@ 3283 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3284 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3285 3286 Collective 3287 3288 Input Parameters: 3289 + fact - the factor matrix obtained with `MatGetFactor()` 3290 . mat - the matrix 3291 - info - options for factorization 3292 3293 Level: developer 3294 3295 Notes: 3296 See `MatLUFactor()` for in-place factorization. See 3297 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3298 3299 Most users should employ the `KSP` interface for linear solvers 3300 instead of working directly with matrix algebra routines such as this. 3301 See, e.g., `KSPCreate()`. 3302 3303 Developer Note: 3304 The Fortran interface is not autogenerated as the 3305 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3306 3307 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3308 @*/ 3309 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3310 { 3311 MatFactorInfo tinfo; 3312 3313 PetscFunctionBegin; 3314 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3315 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3316 PetscValidType(fact, 1); 3317 PetscValidType(mat, 2); 3318 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3319 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, 3320 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3321 3322 MatCheckPreallocated(mat, 2); 3323 if (!info) { 3324 PetscCall(MatFactorInfoInitialize(&tinfo)); 3325 info = &tinfo; 3326 } 3327 3328 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3329 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3330 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3331 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3332 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3333 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3334 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3335 PetscFunctionReturn(PETSC_SUCCESS); 3336 } 3337 3338 /*@ 3339 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3340 symmetric matrix. 3341 3342 Collective 3343 3344 Input Parameters: 3345 + mat - the matrix 3346 . perm - row and column permutations 3347 - info - expected fill as ratio of original fill 3348 3349 Level: developer 3350 3351 Notes: 3352 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3353 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3354 3355 Most users should employ the `KSP` interface for linear solvers 3356 instead of working directly with matrix algebra routines such as this. 3357 See, e.g., `KSPCreate()`. 3358 3359 Developer Note: 3360 The Fortran interface is not autogenerated as the 3361 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3362 3363 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3364 `MatGetOrdering()` 3365 @*/ 3366 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3367 { 3368 MatFactorInfo tinfo; 3369 3370 PetscFunctionBegin; 3371 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3372 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3373 if (info) PetscAssertPointer(info, 3); 3374 PetscValidType(mat, 1); 3375 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3376 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3377 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3378 MatCheckPreallocated(mat, 1); 3379 if (!info) { 3380 PetscCall(MatFactorInfoInitialize(&tinfo)); 3381 info = &tinfo; 3382 } 3383 3384 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3385 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3386 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3387 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3388 PetscFunctionReturn(PETSC_SUCCESS); 3389 } 3390 3391 /*@ 3392 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3393 of a symmetric matrix. 3394 3395 Collective 3396 3397 Input Parameters: 3398 + fact - the factor matrix obtained with `MatGetFactor()` 3399 . mat - the matrix 3400 . perm - row and column permutations 3401 - info - options for factorization, includes 3402 .vb 3403 fill - expected fill as ratio of original fill. 3404 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3405 Run with the option -info to determine an optimal value to use 3406 .ve 3407 3408 Level: developer 3409 3410 Notes: 3411 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3412 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3413 3414 Most users should employ the `KSP` interface for linear solvers 3415 instead of working directly with matrix algebra routines such as this. 3416 See, e.g., `KSPCreate()`. 3417 3418 Developer Note: 3419 The Fortran interface is not autogenerated as the 3420 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3421 3422 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3423 `MatGetOrdering()` 3424 @*/ 3425 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3426 { 3427 MatFactorInfo tinfo; 3428 3429 PetscFunctionBegin; 3430 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3432 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3433 if (info) PetscAssertPointer(info, 4); 3434 PetscValidType(fact, 1); 3435 PetscValidType(mat, 2); 3436 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3437 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3438 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3439 MatCheckPreallocated(mat, 2); 3440 if (!info) { 3441 PetscCall(MatFactorInfoInitialize(&tinfo)); 3442 info = &tinfo; 3443 } 3444 3445 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3446 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3447 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3448 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3449 PetscFunctionReturn(PETSC_SUCCESS); 3450 } 3451 3452 /*@ 3453 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3454 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3455 `MatCholeskyFactorSymbolic()`. 3456 3457 Collective 3458 3459 Input Parameters: 3460 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3461 . mat - the initial matrix that is to be factored 3462 - info - options for factorization 3463 3464 Level: developer 3465 3466 Note: 3467 Most users should employ the `KSP` interface for linear solvers 3468 instead of working directly with matrix algebra routines such as this. 3469 See, e.g., `KSPCreate()`. 3470 3471 Developer Note: 3472 The Fortran interface is not autogenerated as the 3473 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3474 3475 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3476 @*/ 3477 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3478 { 3479 MatFactorInfo tinfo; 3480 3481 PetscFunctionBegin; 3482 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3483 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3484 PetscValidType(fact, 1); 3485 PetscValidType(mat, 2); 3486 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3487 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, 3488 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3489 MatCheckPreallocated(mat, 2); 3490 if (!info) { 3491 PetscCall(MatFactorInfoInitialize(&tinfo)); 3492 info = &tinfo; 3493 } 3494 3495 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3496 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3497 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3498 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3499 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3500 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3501 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3502 PetscFunctionReturn(PETSC_SUCCESS); 3503 } 3504 3505 /*@ 3506 MatQRFactor - Performs in-place QR factorization of matrix. 3507 3508 Collective 3509 3510 Input Parameters: 3511 + mat - the matrix 3512 . col - column permutation 3513 - info - options for factorization, includes 3514 .vb 3515 fill - expected fill as ratio of original fill. 3516 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3517 Run with the option -info to determine an optimal value to use 3518 .ve 3519 3520 Level: developer 3521 3522 Notes: 3523 Most users should employ the `KSP` interface for linear solvers 3524 instead of working directly with matrix algebra routines such as this. 3525 See, e.g., `KSPCreate()`. 3526 3527 This changes the state of the matrix to a factored matrix; it cannot be used 3528 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3529 3530 Developer Note: 3531 The Fortran interface is not autogenerated as the 3532 interface definition cannot be generated correctly [due to MatFactorInfo] 3533 3534 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3535 `MatSetUnfactored()` 3536 @*/ 3537 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3538 { 3539 PetscFunctionBegin; 3540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3541 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3542 if (info) PetscAssertPointer(info, 3); 3543 PetscValidType(mat, 1); 3544 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3545 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3546 MatCheckPreallocated(mat, 1); 3547 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3548 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3549 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3550 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3551 PetscFunctionReturn(PETSC_SUCCESS); 3552 } 3553 3554 /*@ 3555 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3556 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3557 3558 Collective 3559 3560 Input Parameters: 3561 + fact - the factor matrix obtained with `MatGetFactor()` 3562 . mat - the matrix 3563 . col - column permutation 3564 - info - options for factorization, includes 3565 .vb 3566 fill - expected fill as ratio of original fill. 3567 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3568 Run with the option -info to determine an optimal value to use 3569 .ve 3570 3571 Level: developer 3572 3573 Note: 3574 Most users should employ the `KSP` interface for linear solvers 3575 instead of working directly with matrix algebra routines such as this. 3576 See, e.g., `KSPCreate()`. 3577 3578 Developer Note: 3579 The Fortran interface is not autogenerated as the 3580 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3581 3582 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3583 @*/ 3584 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3585 { 3586 MatFactorInfo tinfo; 3587 3588 PetscFunctionBegin; 3589 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3590 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3591 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3592 if (info) PetscAssertPointer(info, 4); 3593 PetscValidType(fact, 1); 3594 PetscValidType(mat, 2); 3595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3596 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3597 MatCheckPreallocated(mat, 2); 3598 if (!info) { 3599 PetscCall(MatFactorInfoInitialize(&tinfo)); 3600 info = &tinfo; 3601 } 3602 3603 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3604 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3605 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3606 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3607 PetscFunctionReturn(PETSC_SUCCESS); 3608 } 3609 3610 /*@ 3611 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3612 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3613 3614 Collective 3615 3616 Input Parameters: 3617 + fact - the factor matrix obtained with `MatGetFactor()` 3618 . mat - the matrix 3619 - info - options for factorization 3620 3621 Level: developer 3622 3623 Notes: 3624 See `MatQRFactor()` for in-place factorization. 3625 3626 Most users should employ the `KSP` interface for linear solvers 3627 instead of working directly with matrix algebra routines such as this. 3628 See, e.g., `KSPCreate()`. 3629 3630 Developer Note: 3631 The Fortran interface is not autogenerated as the 3632 interface definition cannot be generated correctly [due to `MatFactorInfo`] 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) { 3708 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3709 } else PetscUseTypeMethod(mat, solve, b, x); 3710 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3711 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3712 PetscFunctionReturn(PETSC_SUCCESS); 3713 } 3714 3715 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3716 { 3717 Vec b, x; 3718 PetscInt N, i; 3719 PetscErrorCode (*f)(Mat, Vec, Vec); 3720 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3721 3722 PetscFunctionBegin; 3723 if (A->factorerrortype) { 3724 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3725 PetscCall(MatSetInf(X)); 3726 PetscFunctionReturn(PETSC_SUCCESS); 3727 } 3728 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3729 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3730 PetscCall(MatBoundToCPU(A, &Abound)); 3731 if (!Abound) { 3732 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3733 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3734 } 3735 #if PetscDefined(HAVE_CUDA) 3736 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3737 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3738 #elif PetscDefined(HAVE_HIP) 3739 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3740 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3741 #endif 3742 PetscCall(MatGetSize(B, NULL, &N)); 3743 for (i = 0; i < N; i++) { 3744 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3745 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3746 PetscCall((*f)(A, b, x)); 3747 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3748 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3749 } 3750 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3751 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3752 PetscFunctionReturn(PETSC_SUCCESS); 3753 } 3754 3755 /*@ 3756 MatMatSolve - Solves $A X = B$, given a factored matrix. 3757 3758 Neighbor-wise Collective 3759 3760 Input Parameters: 3761 + A - the factored matrix 3762 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3763 3764 Output Parameter: 3765 . X - the result matrix (dense matrix) 3766 3767 Level: developer 3768 3769 Note: 3770 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3771 otherwise, `B` and `X` cannot be the same. 3772 3773 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3774 @*/ 3775 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3776 { 3777 PetscFunctionBegin; 3778 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3779 PetscValidType(A, 1); 3780 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3781 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3782 PetscCheckSameComm(A, 1, B, 2); 3783 PetscCheckSameComm(A, 1, X, 3); 3784 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); 3785 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); 3786 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"); 3787 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3788 MatCheckPreallocated(A, 1); 3789 3790 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3791 if (!A->ops->matsolve) { 3792 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3793 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3794 } else PetscUseTypeMethod(A, matsolve, B, X); 3795 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3796 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3797 PetscFunctionReturn(PETSC_SUCCESS); 3798 } 3799 3800 /*@ 3801 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3802 3803 Neighbor-wise Collective 3804 3805 Input Parameters: 3806 + A - the factored matrix 3807 - B - the right-hand-side matrix (`MATDENSE` matrix) 3808 3809 Output Parameter: 3810 . X - the result matrix (dense matrix) 3811 3812 Level: developer 3813 3814 Note: 3815 The matrices `B` and `X` cannot be the same. I.e., one cannot 3816 call `MatMatSolveTranspose`(A,X,X). 3817 3818 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3819 @*/ 3820 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3821 { 3822 PetscFunctionBegin; 3823 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3824 PetscValidType(A, 1); 3825 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3826 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3827 PetscCheckSameComm(A, 1, B, 2); 3828 PetscCheckSameComm(A, 1, X, 3); 3829 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3830 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); 3831 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); 3832 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); 3833 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"); 3834 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3835 MatCheckPreallocated(A, 1); 3836 3837 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3838 if (!A->ops->matsolvetranspose) { 3839 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3840 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3841 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3842 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3843 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3844 PetscFunctionReturn(PETSC_SUCCESS); 3845 } 3846 3847 /*@ 3848 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3849 3850 Neighbor-wise Collective 3851 3852 Input Parameters: 3853 + A - the factored matrix 3854 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3855 3856 Output Parameter: 3857 . X - the result matrix (dense matrix) 3858 3859 Level: developer 3860 3861 Note: 3862 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 3863 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3864 3865 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3866 @*/ 3867 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3868 { 3869 PetscFunctionBegin; 3870 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3871 PetscValidType(A, 1); 3872 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3873 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3874 PetscCheckSameComm(A, 1, Bt, 2); 3875 PetscCheckSameComm(A, 1, X, 3); 3876 3877 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3878 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); 3879 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); 3880 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"); 3881 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3882 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3883 MatCheckPreallocated(A, 1); 3884 3885 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3886 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3887 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3888 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3889 PetscFunctionReturn(PETSC_SUCCESS); 3890 } 3891 3892 /*@ 3893 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3894 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3895 3896 Neighbor-wise Collective 3897 3898 Input Parameters: 3899 + mat - the factored matrix 3900 - b - the right-hand-side vector 3901 3902 Output Parameter: 3903 . x - the result vector 3904 3905 Level: developer 3906 3907 Notes: 3908 `MatSolve()` should be used for most applications, as it performs 3909 a forward solve followed by a backward solve. 3910 3911 The vectors `b` and `x` cannot be the same, i.e., one cannot 3912 call `MatForwardSolve`(A,x,x). 3913 3914 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3915 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3916 `MatForwardSolve()` solves $U^T*D y = b$, and 3917 `MatBackwardSolve()` solves $U x = y$. 3918 Thus they do not provide a symmetric preconditioner. 3919 3920 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3921 @*/ 3922 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3923 { 3924 PetscFunctionBegin; 3925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3926 PetscValidType(mat, 1); 3927 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3928 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3929 PetscCheckSameComm(mat, 1, b, 2); 3930 PetscCheckSameComm(mat, 1, x, 3); 3931 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3932 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); 3933 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); 3934 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); 3935 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3936 MatCheckPreallocated(mat, 1); 3937 3938 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3939 PetscUseTypeMethod(mat, forwardsolve, b, x); 3940 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3941 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3942 PetscFunctionReturn(PETSC_SUCCESS); 3943 } 3944 3945 /*@ 3946 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3947 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3948 3949 Neighbor-wise Collective 3950 3951 Input Parameters: 3952 + mat - the factored matrix 3953 - b - the right-hand-side vector 3954 3955 Output Parameter: 3956 . x - the result vector 3957 3958 Level: developer 3959 3960 Notes: 3961 `MatSolve()` should be used for most applications, as it performs 3962 a forward solve followed by a backward solve. 3963 3964 The vectors `b` and `x` cannot be the same. I.e., one cannot 3965 call `MatBackwardSolve`(A,x,x). 3966 3967 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3968 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3969 `MatForwardSolve()` solves $U^T*D y = b$, and 3970 `MatBackwardSolve()` solves $U x = y$. 3971 Thus they do not provide a symmetric preconditioner. 3972 3973 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3974 @*/ 3975 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3976 { 3977 PetscFunctionBegin; 3978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3979 PetscValidType(mat, 1); 3980 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3981 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3982 PetscCheckSameComm(mat, 1, b, 2); 3983 PetscCheckSameComm(mat, 1, x, 3); 3984 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3985 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); 3986 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); 3987 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); 3988 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3989 MatCheckPreallocated(mat, 1); 3990 3991 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3992 PetscUseTypeMethod(mat, backwardsolve, b, x); 3993 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3994 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3995 PetscFunctionReturn(PETSC_SUCCESS); 3996 } 3997 3998 /*@ 3999 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4000 4001 Neighbor-wise Collective 4002 4003 Input Parameters: 4004 + mat - the factored matrix 4005 . b - the right-hand-side vector 4006 - y - the vector to be added to 4007 4008 Output Parameter: 4009 . x - the result vector 4010 4011 Level: developer 4012 4013 Note: 4014 The vectors `b` and `x` cannot be the same. I.e., one cannot 4015 call `MatSolveAdd`(A,x,y,x). 4016 4017 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4018 @*/ 4019 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4020 { 4021 PetscScalar one = 1.0; 4022 Vec tmp; 4023 4024 PetscFunctionBegin; 4025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4026 PetscValidType(mat, 1); 4027 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4028 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4029 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4030 PetscCheckSameComm(mat, 1, b, 2); 4031 PetscCheckSameComm(mat, 1, y, 3); 4032 PetscCheckSameComm(mat, 1, x, 4); 4033 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4034 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); 4035 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); 4036 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); 4037 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); 4038 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); 4039 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4040 MatCheckPreallocated(mat, 1); 4041 4042 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4043 PetscCall(VecFlag(x, mat->factorerrortype)); 4044 if (mat->factorerrortype) { 4045 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4046 } else if (mat->ops->solveadd) { 4047 PetscUseTypeMethod(mat, solveadd, b, y, x); 4048 } else { 4049 /* do the solve then the add manually */ 4050 if (x != y) { 4051 PetscCall(MatSolve(mat, b, x)); 4052 PetscCall(VecAXPY(x, one, y)); 4053 } else { 4054 PetscCall(VecDuplicate(x, &tmp)); 4055 PetscCall(VecCopy(x, tmp)); 4056 PetscCall(MatSolve(mat, b, x)); 4057 PetscCall(VecAXPY(x, one, tmp)); 4058 PetscCall(VecDestroy(&tmp)); 4059 } 4060 } 4061 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4062 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4063 PetscFunctionReturn(PETSC_SUCCESS); 4064 } 4065 4066 /*@ 4067 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4068 4069 Neighbor-wise Collective 4070 4071 Input Parameters: 4072 + mat - the factored matrix 4073 - b - the right-hand-side vector 4074 4075 Output Parameter: 4076 . x - the result vector 4077 4078 Level: developer 4079 4080 Notes: 4081 The vectors `b` and `x` cannot be the same. I.e., one cannot 4082 call `MatSolveTranspose`(A,x,x). 4083 4084 Most users should employ the `KSP` interface for linear solvers 4085 instead of working directly with matrix algebra routines such as this. 4086 See, e.g., `KSPCreate()`. 4087 4088 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4089 @*/ 4090 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4091 { 4092 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4093 4094 PetscFunctionBegin; 4095 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4096 PetscValidType(mat, 1); 4097 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4098 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4099 PetscCheckSameComm(mat, 1, b, 2); 4100 PetscCheckSameComm(mat, 1, x, 3); 4101 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4102 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); 4103 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); 4104 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4105 MatCheckPreallocated(mat, 1); 4106 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4107 PetscCall(VecFlag(x, mat->factorerrortype)); 4108 if (mat->factorerrortype) { 4109 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4110 } else { 4111 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4112 PetscCall((*f)(mat, b, x)); 4113 } 4114 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4115 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4116 PetscFunctionReturn(PETSC_SUCCESS); 4117 } 4118 4119 /*@ 4120 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4121 factored matrix. 4122 4123 Neighbor-wise Collective 4124 4125 Input Parameters: 4126 + mat - the factored matrix 4127 . b - the right-hand-side vector 4128 - y - the vector to be added to 4129 4130 Output Parameter: 4131 . x - the result vector 4132 4133 Level: developer 4134 4135 Note: 4136 The vectors `b` and `x` cannot be the same. I.e., one cannot 4137 call `MatSolveTransposeAdd`(A,x,y,x). 4138 4139 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4140 @*/ 4141 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4142 { 4143 PetscScalar one = 1.0; 4144 Vec tmp; 4145 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4146 4147 PetscFunctionBegin; 4148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4149 PetscValidType(mat, 1); 4150 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4151 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4152 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4153 PetscCheckSameComm(mat, 1, b, 2); 4154 PetscCheckSameComm(mat, 1, y, 3); 4155 PetscCheckSameComm(mat, 1, x, 4); 4156 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4157 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); 4158 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); 4159 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); 4160 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); 4161 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4162 MatCheckPreallocated(mat, 1); 4163 4164 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4165 PetscCall(VecFlag(x, mat->factorerrortype)); 4166 if (mat->factorerrortype) { 4167 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4168 } else if (f) { 4169 PetscCall((*f)(mat, b, y, x)); 4170 } else { 4171 /* do the solve then the add manually */ 4172 if (x != y) { 4173 PetscCall(MatSolveTranspose(mat, b, x)); 4174 PetscCall(VecAXPY(x, one, y)); 4175 } else { 4176 PetscCall(VecDuplicate(x, &tmp)); 4177 PetscCall(VecCopy(x, tmp)); 4178 PetscCall(MatSolveTranspose(mat, b, x)); 4179 PetscCall(VecAXPY(x, one, tmp)); 4180 PetscCall(VecDestroy(&tmp)); 4181 } 4182 } 4183 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4184 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4185 PetscFunctionReturn(PETSC_SUCCESS); 4186 } 4187 4188 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4189 /*@ 4190 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4191 4192 Neighbor-wise Collective 4193 4194 Input Parameters: 4195 + mat - the matrix 4196 . b - the right-hand side 4197 . omega - the relaxation factor 4198 . flag - flag indicating the type of SOR (see below) 4199 . shift - diagonal shift 4200 . its - the number of iterations 4201 - lits - the number of local iterations 4202 4203 Output Parameter: 4204 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4205 4206 SOR Flags: 4207 + `SOR_FORWARD_SWEEP` - forward SOR 4208 . `SOR_BACKWARD_SWEEP` - backward SOR 4209 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4210 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4211 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4212 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4213 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4214 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4215 upper/lower triangular part of matrix to 4216 vector (with omega) 4217 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4218 4219 Level: developer 4220 4221 Notes: 4222 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4223 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4224 on each processor. 4225 4226 Application programmers will not generally use `MatSOR()` directly, 4227 but instead will employ the `KSP`/`PC` interface. 4228 4229 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4230 4231 Most users should employ the `KSP` interface for linear solvers 4232 instead of working directly with matrix algebra routines such as this. 4233 See, e.g., `KSPCreate()`. 4234 4235 Vectors `x` and `b` CANNOT be the same 4236 4237 The flags are implemented as bitwise inclusive or operations. 4238 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4239 to specify a zero initial guess for SSOR. 4240 4241 Developer Note: 4242 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4243 4244 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4245 @*/ 4246 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4247 { 4248 PetscFunctionBegin; 4249 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4250 PetscValidType(mat, 1); 4251 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4252 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4253 PetscCheckSameComm(mat, 1, b, 2); 4254 PetscCheckSameComm(mat, 1, x, 8); 4255 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4256 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4257 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); 4258 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); 4259 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); 4260 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4261 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4262 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4263 4264 MatCheckPreallocated(mat, 1); 4265 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4266 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4267 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4268 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4269 PetscFunctionReturn(PETSC_SUCCESS); 4270 } 4271 4272 /* 4273 Default matrix copy routine. 4274 */ 4275 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4276 { 4277 PetscInt i, rstart = 0, rend = 0, nz; 4278 const PetscInt *cwork; 4279 const PetscScalar *vwork; 4280 4281 PetscFunctionBegin; 4282 if (B->assembled) PetscCall(MatZeroEntries(B)); 4283 if (str == SAME_NONZERO_PATTERN) { 4284 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4285 for (i = rstart; i < rend; i++) { 4286 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4287 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4288 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4289 } 4290 } else { 4291 PetscCall(MatAYPX(B, 0.0, A, str)); 4292 } 4293 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4294 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4295 PetscFunctionReturn(PETSC_SUCCESS); 4296 } 4297 4298 /*@ 4299 MatCopy - Copies a matrix to another matrix. 4300 4301 Collective 4302 4303 Input Parameters: 4304 + A - the matrix 4305 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4306 4307 Output Parameter: 4308 . B - where the copy is put 4309 4310 Level: intermediate 4311 4312 Notes: 4313 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4314 4315 `MatCopy()` copies the matrix entries of a matrix to another existing 4316 matrix (after first zeroing the second matrix). A related routine is 4317 `MatConvert()`, which first creates a new matrix and then copies the data. 4318 4319 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4320 @*/ 4321 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4322 { 4323 PetscInt i; 4324 4325 PetscFunctionBegin; 4326 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4327 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4328 PetscValidType(A, 1); 4329 PetscValidType(B, 2); 4330 PetscCheckSameComm(A, 1, B, 2); 4331 MatCheckPreallocated(B, 2); 4332 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4333 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4334 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, 4335 A->cmap->N, B->cmap->N); 4336 MatCheckPreallocated(A, 1); 4337 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4338 4339 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4340 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4341 else PetscCall(MatCopy_Basic(A, B, str)); 4342 4343 B->stencil.dim = A->stencil.dim; 4344 B->stencil.noc = A->stencil.noc; 4345 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4346 B->stencil.dims[i] = A->stencil.dims[i]; 4347 B->stencil.starts[i] = A->stencil.starts[i]; 4348 } 4349 4350 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4351 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4352 PetscFunctionReturn(PETSC_SUCCESS); 4353 } 4354 4355 /*@ 4356 MatConvert - Converts a matrix to another matrix, either of the same 4357 or different type. 4358 4359 Collective 4360 4361 Input Parameters: 4362 + mat - the matrix 4363 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4364 same type as the original matrix. 4365 - reuse - denotes if the destination matrix is to be created or reused. 4366 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 4367 `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). 4368 4369 Output Parameter: 4370 . M - pointer to place new matrix 4371 4372 Level: intermediate 4373 4374 Notes: 4375 `MatConvert()` first creates a new matrix and then copies the data from 4376 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4377 entries of one matrix to another already existing matrix context. 4378 4379 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4380 the MPI communicator of the generated matrix is always the same as the communicator 4381 of the input matrix. 4382 4383 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4384 @*/ 4385 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4386 { 4387 PetscBool sametype, issame, flg; 4388 PetscBool3 issymmetric, ishermitian; 4389 char convname[256], mtype[256]; 4390 Mat B; 4391 4392 PetscFunctionBegin; 4393 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4394 PetscValidType(mat, 1); 4395 PetscAssertPointer(M, 4); 4396 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4397 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4398 MatCheckPreallocated(mat, 1); 4399 4400 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4401 if (flg) newtype = mtype; 4402 4403 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4404 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4405 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4406 if (reuse == MAT_REUSE_MATRIX) { 4407 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4408 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4409 } 4410 4411 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4412 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4413 PetscFunctionReturn(PETSC_SUCCESS); 4414 } 4415 4416 /* Cache Mat options because some converters use MatHeaderReplace */ 4417 issymmetric = mat->symmetric; 4418 ishermitian = mat->hermitian; 4419 4420 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4421 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4422 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4423 } else { 4424 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4425 const char *prefix[3] = {"seq", "mpi", ""}; 4426 PetscInt i; 4427 /* 4428 Order of precedence: 4429 0) See if newtype is a superclass of the current matrix. 4430 1) See if a specialized converter is known to the current matrix. 4431 2) See if a specialized converter is known to the desired matrix class. 4432 3) See if a good general converter is registered for the desired class 4433 (as of 6/27/03 only MATMPIADJ falls into this category). 4434 4) See if a good general converter is known for the current matrix. 4435 5) Use a really basic converter. 4436 */ 4437 4438 /* 0) See if newtype is a superclass of the current matrix. 4439 i.e mat is mpiaij and newtype is aij */ 4440 for (i = 0; i < 2; i++) { 4441 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4443 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4444 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4445 if (flg) { 4446 if (reuse == MAT_INPLACE_MATRIX) { 4447 PetscCall(PetscInfo(mat, "Early return\n")); 4448 PetscFunctionReturn(PETSC_SUCCESS); 4449 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4450 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4451 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4452 PetscFunctionReturn(PETSC_SUCCESS); 4453 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4454 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4455 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4456 PetscFunctionReturn(PETSC_SUCCESS); 4457 } 4458 } 4459 } 4460 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4461 for (i = 0; i < 3; i++) { 4462 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4463 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4464 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4465 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4466 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4467 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4468 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4469 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4470 if (conv) goto foundconv; 4471 } 4472 4473 /* 2) See if a specialized converter is known to the desired matrix class. */ 4474 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4475 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4476 PetscCall(MatSetType(B, newtype)); 4477 for (i = 0; i < 3; i++) { 4478 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4479 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4480 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4481 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4482 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4483 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4484 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4485 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4486 if (conv) { 4487 PetscCall(MatDestroy(&B)); 4488 goto foundconv; 4489 } 4490 } 4491 4492 /* 3) See if a good general converter is registered for the desired class */ 4493 conv = B->ops->convertfrom; 4494 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4495 PetscCall(MatDestroy(&B)); 4496 if (conv) goto foundconv; 4497 4498 /* 4) See if a good general converter is known for the current matrix */ 4499 if (mat->ops->convert) conv = mat->ops->convert; 4500 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4501 if (conv) goto foundconv; 4502 4503 /* 5) Use a really basic converter. */ 4504 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4505 conv = MatConvert_Basic; 4506 4507 foundconv: 4508 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4509 PetscCall((*conv)(mat, newtype, reuse, M)); 4510 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4511 /* the block sizes must be same if the mappings are copied over */ 4512 (*M)->rmap->bs = mat->rmap->bs; 4513 (*M)->cmap->bs = mat->cmap->bs; 4514 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4515 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4516 (*M)->rmap->mapping = mat->rmap->mapping; 4517 (*M)->cmap->mapping = mat->cmap->mapping; 4518 } 4519 (*M)->stencil.dim = mat->stencil.dim; 4520 (*M)->stencil.noc = mat->stencil.noc; 4521 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4522 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4523 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4524 } 4525 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4526 } 4527 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4528 4529 /* Copy Mat options */ 4530 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4531 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4532 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4533 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4534 PetscFunctionReturn(PETSC_SUCCESS); 4535 } 4536 4537 /*@ 4538 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4539 4540 Not Collective 4541 4542 Input Parameter: 4543 . mat - the matrix, must be a factored matrix 4544 4545 Output Parameter: 4546 . type - the string name of the package (do not free this string) 4547 4548 Level: intermediate 4549 4550 Fortran Note: 4551 Pass in an empty string that is long enough and the package name will be copied into it. 4552 4553 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4554 @*/ 4555 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4556 { 4557 PetscErrorCode (*conv)(Mat, MatSolverType *); 4558 4559 PetscFunctionBegin; 4560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4561 PetscValidType(mat, 1); 4562 PetscAssertPointer(type, 2); 4563 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4564 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4565 if (conv) PetscCall((*conv)(mat, type)); 4566 else *type = MATSOLVERPETSC; 4567 PetscFunctionReturn(PETSC_SUCCESS); 4568 } 4569 4570 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4571 struct _MatSolverTypeForSpecifcType { 4572 MatType mtype; 4573 /* no entry for MAT_FACTOR_NONE */ 4574 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4575 MatSolverTypeForSpecifcType next; 4576 }; 4577 4578 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4579 struct _MatSolverTypeHolder { 4580 char *name; 4581 MatSolverTypeForSpecifcType handlers; 4582 MatSolverTypeHolder next; 4583 }; 4584 4585 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4586 4587 /*@C 4588 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4589 4590 Logically Collective, No Fortran Support 4591 4592 Input Parameters: 4593 + package - name of the package, for example petsc or superlu 4594 . mtype - the matrix type that works with this package 4595 . ftype - the type of factorization supported by the package 4596 - createfactor - routine that will create the factored matrix ready to be used 4597 4598 Level: developer 4599 4600 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4601 `MatGetFactor()` 4602 @*/ 4603 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4604 { 4605 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4606 PetscBool flg; 4607 MatSolverTypeForSpecifcType inext, iprev = NULL; 4608 4609 PetscFunctionBegin; 4610 PetscCall(MatInitializePackage()); 4611 if (!next) { 4612 PetscCall(PetscNew(&MatSolverTypeHolders)); 4613 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4614 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4615 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4616 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4617 PetscFunctionReturn(PETSC_SUCCESS); 4618 } 4619 while (next) { 4620 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4621 if (flg) { 4622 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4623 inext = next->handlers; 4624 while (inext) { 4625 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4626 if (flg) { 4627 inext->createfactor[(int)ftype - 1] = createfactor; 4628 PetscFunctionReturn(PETSC_SUCCESS); 4629 } 4630 iprev = inext; 4631 inext = inext->next; 4632 } 4633 PetscCall(PetscNew(&iprev->next)); 4634 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4635 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4636 PetscFunctionReturn(PETSC_SUCCESS); 4637 } 4638 prev = next; 4639 next = next->next; 4640 } 4641 PetscCall(PetscNew(&prev->next)); 4642 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4643 PetscCall(PetscNew(&prev->next->handlers)); 4644 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4645 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4646 PetscFunctionReturn(PETSC_SUCCESS); 4647 } 4648 4649 /*@C 4650 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4651 4652 Input Parameters: 4653 + 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 4654 . ftype - the type of factorization supported by the type 4655 - mtype - the matrix type that works with this type 4656 4657 Output Parameters: 4658 + foundtype - `PETSC_TRUE` if the type was registered 4659 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4660 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4661 4662 Calling sequence of `createfactor`: 4663 + A - the matrix providing the factor matrix 4664 . ftype - the `MatFactorType` of the factor requested 4665 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4666 4667 Level: developer 4668 4669 Note: 4670 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4671 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4672 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4673 4674 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4675 `MatInitializePackage()` 4676 @*/ 4677 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4678 { 4679 MatSolverTypeHolder next = MatSolverTypeHolders; 4680 PetscBool flg; 4681 MatSolverTypeForSpecifcType inext; 4682 4683 PetscFunctionBegin; 4684 if (foundtype) *foundtype = PETSC_FALSE; 4685 if (foundmtype) *foundmtype = PETSC_FALSE; 4686 if (createfactor) *createfactor = NULL; 4687 4688 if (type) { 4689 while (next) { 4690 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4691 if (flg) { 4692 if (foundtype) *foundtype = PETSC_TRUE; 4693 inext = next->handlers; 4694 while (inext) { 4695 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4696 if (flg) { 4697 if (foundmtype) *foundmtype = PETSC_TRUE; 4698 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4699 PetscFunctionReturn(PETSC_SUCCESS); 4700 } 4701 inext = inext->next; 4702 } 4703 } 4704 next = next->next; 4705 } 4706 } else { 4707 while (next) { 4708 inext = next->handlers; 4709 while (inext) { 4710 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4711 if (flg && inext->createfactor[(int)ftype - 1]) { 4712 if (foundtype) *foundtype = PETSC_TRUE; 4713 if (foundmtype) *foundmtype = PETSC_TRUE; 4714 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4715 PetscFunctionReturn(PETSC_SUCCESS); 4716 } 4717 inext = inext->next; 4718 } 4719 next = next->next; 4720 } 4721 /* try with base classes inext->mtype */ 4722 next = MatSolverTypeHolders; 4723 while (next) { 4724 inext = next->handlers; 4725 while (inext) { 4726 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4727 if (flg && inext->createfactor[(int)ftype - 1]) { 4728 if (foundtype) *foundtype = PETSC_TRUE; 4729 if (foundmtype) *foundmtype = PETSC_TRUE; 4730 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4731 PetscFunctionReturn(PETSC_SUCCESS); 4732 } 4733 inext = inext->next; 4734 } 4735 next = next->next; 4736 } 4737 } 4738 PetscFunctionReturn(PETSC_SUCCESS); 4739 } 4740 4741 PetscErrorCode MatSolverTypeDestroy(void) 4742 { 4743 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4744 MatSolverTypeForSpecifcType inext, iprev; 4745 4746 PetscFunctionBegin; 4747 while (next) { 4748 PetscCall(PetscFree(next->name)); 4749 inext = next->handlers; 4750 while (inext) { 4751 PetscCall(PetscFree(inext->mtype)); 4752 iprev = inext; 4753 inext = inext->next; 4754 PetscCall(PetscFree(iprev)); 4755 } 4756 prev = next; 4757 next = next->next; 4758 PetscCall(PetscFree(prev)); 4759 } 4760 MatSolverTypeHolders = NULL; 4761 PetscFunctionReturn(PETSC_SUCCESS); 4762 } 4763 4764 /*@ 4765 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4766 4767 Logically Collective 4768 4769 Input Parameter: 4770 . mat - the matrix 4771 4772 Output Parameter: 4773 . flg - `PETSC_TRUE` if uses the ordering 4774 4775 Level: developer 4776 4777 Note: 4778 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4779 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4780 4781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4782 @*/ 4783 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4784 { 4785 PetscFunctionBegin; 4786 *flg = mat->canuseordering; 4787 PetscFunctionReturn(PETSC_SUCCESS); 4788 } 4789 4790 /*@ 4791 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4792 4793 Logically Collective 4794 4795 Input Parameters: 4796 + mat - the matrix obtained with `MatGetFactor()` 4797 - ftype - the factorization type to be used 4798 4799 Output Parameter: 4800 . otype - the preferred ordering type 4801 4802 Level: developer 4803 4804 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4805 @*/ 4806 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4807 { 4808 PetscFunctionBegin; 4809 *otype = mat->preferredordering[ftype]; 4810 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4811 PetscFunctionReturn(PETSC_SUCCESS); 4812 } 4813 4814 /*@ 4815 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4816 4817 Collective 4818 4819 Input Parameters: 4820 + mat - the matrix 4821 . 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 4822 the other criteria is returned 4823 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4824 4825 Output Parameter: 4826 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4827 4828 Options Database Keys: 4829 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4830 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4831 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4832 4833 Level: intermediate 4834 4835 Notes: 4836 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4837 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4838 4839 Users usually access the factorization solvers via `KSP` 4840 4841 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4842 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 4843 4844 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4845 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4846 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4847 4848 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4849 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4850 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4851 4852 Developer Note: 4853 This should actually be called `MatCreateFactor()` since it creates a new factor object 4854 4855 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4856 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4857 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4858 @*/ 4859 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4860 { 4861 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4862 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4863 4864 PetscFunctionBegin; 4865 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4866 PetscValidType(mat, 1); 4867 4868 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4869 MatCheckPreallocated(mat, 1); 4870 4871 PetscCall(MatIsShell(mat, &shell)); 4872 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4873 if (hasop) { 4874 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4875 PetscFunctionReturn(PETSC_SUCCESS); 4876 } 4877 4878 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4879 if (!foundtype) { 4880 if (type) { 4881 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], 4882 ((PetscObject)mat)->type_name, type); 4883 } else { 4884 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); 4885 } 4886 } 4887 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4888 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); 4889 4890 PetscCall((*conv)(mat, ftype, f)); 4891 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4892 PetscFunctionReturn(PETSC_SUCCESS); 4893 } 4894 4895 /*@ 4896 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4897 4898 Not Collective 4899 4900 Input Parameters: 4901 + mat - the matrix 4902 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4903 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4904 4905 Output Parameter: 4906 . flg - PETSC_TRUE if the factorization is available 4907 4908 Level: intermediate 4909 4910 Notes: 4911 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4912 such as pastix, superlu, mumps etc. 4913 4914 PETSc must have been ./configure to use the external solver, using the option --download-package 4915 4916 Developer Note: 4917 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4918 4919 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4920 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4921 @*/ 4922 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4923 { 4924 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4925 4926 PetscFunctionBegin; 4927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4928 PetscAssertPointer(flg, 4); 4929 4930 *flg = PETSC_FALSE; 4931 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4932 4933 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4934 MatCheckPreallocated(mat, 1); 4935 4936 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4937 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4938 PetscFunctionReturn(PETSC_SUCCESS); 4939 } 4940 4941 /*@ 4942 MatDuplicate - Duplicates a matrix including the non-zero structure. 4943 4944 Collective 4945 4946 Input Parameters: 4947 + mat - the matrix 4948 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4949 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4950 4951 Output Parameter: 4952 . M - pointer to place new matrix 4953 4954 Level: intermediate 4955 4956 Notes: 4957 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4958 4959 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4960 4961 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. 4962 4963 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4964 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4965 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4966 4967 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4968 @*/ 4969 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4970 { 4971 Mat B; 4972 VecType vtype; 4973 PetscInt i; 4974 PetscObject dm, container_h, container_d; 4975 void (*viewf)(void); 4976 4977 PetscFunctionBegin; 4978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4979 PetscValidType(mat, 1); 4980 PetscAssertPointer(M, 3); 4981 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4982 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4983 MatCheckPreallocated(mat, 1); 4984 4985 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4986 PetscUseTypeMethod(mat, duplicate, op, M); 4987 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4988 B = *M; 4989 4990 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4991 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4992 PetscCall(MatGetVecType(mat, &vtype)); 4993 PetscCall(MatSetVecType(B, vtype)); 4994 4995 B->stencil.dim = mat->stencil.dim; 4996 B->stencil.noc = mat->stencil.noc; 4997 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4998 B->stencil.dims[i] = mat->stencil.dims[i]; 4999 B->stencil.starts[i] = mat->stencil.starts[i]; 5000 } 5001 5002 B->nooffproczerorows = mat->nooffproczerorows; 5003 B->nooffprocentries = mat->nooffprocentries; 5004 5005 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5006 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5007 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5008 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5009 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5010 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5011 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5012 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5013 PetscFunctionReturn(PETSC_SUCCESS); 5014 } 5015 5016 /*@ 5017 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5018 5019 Logically Collective 5020 5021 Input Parameter: 5022 . mat - the matrix 5023 5024 Output Parameter: 5025 . v - the diagonal of the matrix 5026 5027 Level: intermediate 5028 5029 Note: 5030 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5031 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5032 is larger than `ndiag`, the values of the remaining entries are unspecified. 5033 5034 Currently only correct in parallel for square matrices. 5035 5036 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5037 @*/ 5038 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5039 { 5040 PetscFunctionBegin; 5041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5042 PetscValidType(mat, 1); 5043 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5044 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5045 MatCheckPreallocated(mat, 1); 5046 if (PetscDefined(USE_DEBUG)) { 5047 PetscInt nv, row, col, ndiag; 5048 5049 PetscCall(VecGetLocalSize(v, &nv)); 5050 PetscCall(MatGetLocalSize(mat, &row, &col)); 5051 ndiag = PetscMin(row, col); 5052 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); 5053 } 5054 5055 PetscUseTypeMethod(mat, getdiagonal, v); 5056 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5057 PetscFunctionReturn(PETSC_SUCCESS); 5058 } 5059 5060 /*@ 5061 MatGetRowMin - Gets the minimum value (of the real part) of each 5062 row of the matrix 5063 5064 Logically Collective 5065 5066 Input Parameter: 5067 . mat - the matrix 5068 5069 Output Parameters: 5070 + v - the vector for storing the maximums 5071 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5072 5073 Level: intermediate 5074 5075 Note: 5076 The result of this call are the same as if one converted the matrix to dense format 5077 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5078 5079 This code is only implemented for a couple of matrix formats. 5080 5081 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5082 `MatGetRowMax()` 5083 @*/ 5084 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5085 { 5086 PetscFunctionBegin; 5087 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5088 PetscValidType(mat, 1); 5089 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5090 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5091 5092 if (!mat->cmap->N) { 5093 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5094 if (idx) { 5095 PetscInt i, m = mat->rmap->n; 5096 for (i = 0; i < m; i++) idx[i] = -1; 5097 } 5098 } else { 5099 MatCheckPreallocated(mat, 1); 5100 } 5101 PetscUseTypeMethod(mat, getrowmin, v, idx); 5102 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5103 PetscFunctionReturn(PETSC_SUCCESS); 5104 } 5105 5106 /*@ 5107 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5108 row of the matrix 5109 5110 Logically Collective 5111 5112 Input Parameter: 5113 . mat - the matrix 5114 5115 Output Parameters: 5116 + v - the vector for storing the minimums 5117 - idx - the indices of the column found for each row (or `NULL` if not needed) 5118 5119 Level: intermediate 5120 5121 Notes: 5122 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5123 row is 0 (the first column). 5124 5125 This code is only implemented for a couple of matrix formats. 5126 5127 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5128 @*/ 5129 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5130 { 5131 PetscFunctionBegin; 5132 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5133 PetscValidType(mat, 1); 5134 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5135 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5136 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5137 5138 if (!mat->cmap->N) { 5139 PetscCall(VecSet(v, 0.0)); 5140 if (idx) { 5141 PetscInt i, m = mat->rmap->n; 5142 for (i = 0; i < m; i++) idx[i] = -1; 5143 } 5144 } else { 5145 MatCheckPreallocated(mat, 1); 5146 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5147 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5148 } 5149 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5150 PetscFunctionReturn(PETSC_SUCCESS); 5151 } 5152 5153 /*@ 5154 MatGetRowMax - Gets the maximum value (of the real part) of each 5155 row of the matrix 5156 5157 Logically Collective 5158 5159 Input Parameter: 5160 . mat - the matrix 5161 5162 Output Parameters: 5163 + v - the vector for storing the maximums 5164 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5165 5166 Level: intermediate 5167 5168 Notes: 5169 The result of this call are the same as if one converted the matrix to dense format 5170 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5171 5172 This code is only implemented for a couple of matrix formats. 5173 5174 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5175 @*/ 5176 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5177 { 5178 PetscFunctionBegin; 5179 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5180 PetscValidType(mat, 1); 5181 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5182 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5183 5184 if (!mat->cmap->N) { 5185 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5186 if (idx) { 5187 PetscInt i, m = mat->rmap->n; 5188 for (i = 0; i < m; i++) idx[i] = -1; 5189 } 5190 } else { 5191 MatCheckPreallocated(mat, 1); 5192 PetscUseTypeMethod(mat, getrowmax, v, idx); 5193 } 5194 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5195 PetscFunctionReturn(PETSC_SUCCESS); 5196 } 5197 5198 /*@ 5199 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5200 row of the matrix 5201 5202 Logically Collective 5203 5204 Input Parameter: 5205 . mat - the matrix 5206 5207 Output Parameters: 5208 + v - the vector for storing the maximums 5209 - idx - the indices of the column found for each row (or `NULL` if not needed) 5210 5211 Level: intermediate 5212 5213 Notes: 5214 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5215 row is 0 (the first column). 5216 5217 This code is only implemented for a couple of matrix formats. 5218 5219 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5220 @*/ 5221 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5222 { 5223 PetscFunctionBegin; 5224 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5225 PetscValidType(mat, 1); 5226 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5227 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5228 5229 if (!mat->cmap->N) { 5230 PetscCall(VecSet(v, 0.0)); 5231 if (idx) { 5232 PetscInt i, m = mat->rmap->n; 5233 for (i = 0; i < m; i++) idx[i] = -1; 5234 } 5235 } else { 5236 MatCheckPreallocated(mat, 1); 5237 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5238 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5239 } 5240 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5241 PetscFunctionReturn(PETSC_SUCCESS); 5242 } 5243 5244 /*@ 5245 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5246 5247 Logically Collective 5248 5249 Input Parameter: 5250 . mat - the matrix 5251 5252 Output Parameter: 5253 . v - the vector for storing the sum 5254 5255 Level: intermediate 5256 5257 This code is only implemented for a couple of matrix formats. 5258 5259 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5260 @*/ 5261 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5262 { 5263 PetscFunctionBegin; 5264 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5265 PetscValidType(mat, 1); 5266 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5268 5269 if (!mat->cmap->N) { 5270 PetscCall(VecSet(v, 0.0)); 5271 } else { 5272 MatCheckPreallocated(mat, 1); 5273 PetscUseTypeMethod(mat, getrowsumabs, v); 5274 } 5275 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5276 PetscFunctionReturn(PETSC_SUCCESS); 5277 } 5278 5279 /*@ 5280 MatGetRowSum - Gets the sum of each row of the matrix 5281 5282 Logically or Neighborhood Collective 5283 5284 Input Parameter: 5285 . mat - the matrix 5286 5287 Output Parameter: 5288 . v - the vector for storing the sum of rows 5289 5290 Level: intermediate 5291 5292 Note: 5293 This code is slow since it is not currently specialized for different formats 5294 5295 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5296 @*/ 5297 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5298 { 5299 Vec ones; 5300 5301 PetscFunctionBegin; 5302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5303 PetscValidType(mat, 1); 5304 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5305 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5306 MatCheckPreallocated(mat, 1); 5307 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5308 PetscCall(VecSet(ones, 1.)); 5309 PetscCall(MatMult(mat, ones, v)); 5310 PetscCall(VecDestroy(&ones)); 5311 PetscFunctionReturn(PETSC_SUCCESS); 5312 } 5313 5314 /*@ 5315 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5316 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5317 5318 Collective 5319 5320 Input Parameter: 5321 . mat - the matrix to provide the transpose 5322 5323 Output Parameter: 5324 . 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 5325 5326 Level: advanced 5327 5328 Note: 5329 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 5330 routine allows bypassing that call. 5331 5332 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5333 @*/ 5334 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5335 { 5336 MatParentState *rb = NULL; 5337 5338 PetscFunctionBegin; 5339 PetscCall(PetscNew(&rb)); 5340 rb->id = ((PetscObject)mat)->id; 5341 rb->state = 0; 5342 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5343 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5344 PetscFunctionReturn(PETSC_SUCCESS); 5345 } 5346 5347 /*@ 5348 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5349 5350 Collective 5351 5352 Input Parameters: 5353 + mat - the matrix to transpose 5354 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5355 5356 Output Parameter: 5357 . B - the transpose of the matrix 5358 5359 Level: intermediate 5360 5361 Notes: 5362 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5363 5364 `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 5365 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5366 5367 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. 5368 5369 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5370 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5371 5372 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5373 5374 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5375 5376 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5377 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5378 @*/ 5379 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5380 { 5381 PetscContainer rB = NULL; 5382 MatParentState *rb = NULL; 5383 5384 PetscFunctionBegin; 5385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5386 PetscValidType(mat, 1); 5387 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5388 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5389 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5390 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5391 MatCheckPreallocated(mat, 1); 5392 if (reuse == MAT_REUSE_MATRIX) { 5393 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5394 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5395 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5396 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5397 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5398 } 5399 5400 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5401 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5402 PetscUseTypeMethod(mat, transpose, reuse, B); 5403 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5404 } 5405 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5406 5407 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5408 if (reuse != MAT_INPLACE_MATRIX) { 5409 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5410 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5411 rb->state = ((PetscObject)mat)->state; 5412 rb->nonzerostate = mat->nonzerostate; 5413 } 5414 PetscFunctionReturn(PETSC_SUCCESS); 5415 } 5416 5417 /*@ 5418 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5419 5420 Collective 5421 5422 Input Parameter: 5423 . A - the matrix to transpose 5424 5425 Output Parameter: 5426 . 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 5427 numerical portion. 5428 5429 Level: intermediate 5430 5431 Note: 5432 This is not supported for many matrix types, use `MatTranspose()` in those cases 5433 5434 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5435 @*/ 5436 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5437 { 5438 PetscFunctionBegin; 5439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5440 PetscValidType(A, 1); 5441 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5442 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5443 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5444 PetscUseTypeMethod(A, transposesymbolic, B); 5445 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5446 5447 PetscCall(MatTransposeSetPrecursor(A, *B)); 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5452 { 5453 PetscContainer rB; 5454 MatParentState *rb; 5455 5456 PetscFunctionBegin; 5457 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5458 PetscValidType(A, 1); 5459 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5460 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5461 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5462 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5463 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5464 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5465 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5466 PetscFunctionReturn(PETSC_SUCCESS); 5467 } 5468 5469 /*@ 5470 MatIsTranspose - Test whether a matrix is another one's transpose, 5471 or its own, in which case it tests symmetry. 5472 5473 Collective 5474 5475 Input Parameters: 5476 + A - the matrix to test 5477 . B - the matrix to test against, this can equal the first parameter 5478 - tol - tolerance, differences between entries smaller than this are counted as zero 5479 5480 Output Parameter: 5481 . flg - the result 5482 5483 Level: intermediate 5484 5485 Notes: 5486 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5487 test involves parallel copies of the block off-diagonal parts of the matrix. 5488 5489 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5490 @*/ 5491 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5492 { 5493 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5494 5495 PetscFunctionBegin; 5496 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5497 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5498 PetscAssertPointer(flg, 4); 5499 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5500 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5501 *flg = PETSC_FALSE; 5502 if (f && g) { 5503 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5504 PetscCall((*f)(A, B, tol, flg)); 5505 } else { 5506 MatType mattype; 5507 5508 PetscCall(MatGetType(f ? B : A, &mattype)); 5509 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5510 } 5511 PetscFunctionReturn(PETSC_SUCCESS); 5512 } 5513 5514 /*@ 5515 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5516 5517 Collective 5518 5519 Input Parameters: 5520 + mat - the matrix to transpose and complex conjugate 5521 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5522 5523 Output Parameter: 5524 . B - the Hermitian transpose 5525 5526 Level: intermediate 5527 5528 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5529 @*/ 5530 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5531 { 5532 PetscFunctionBegin; 5533 PetscCall(MatTranspose(mat, reuse, B)); 5534 #if defined(PETSC_USE_COMPLEX) 5535 PetscCall(MatConjugate(*B)); 5536 #endif 5537 PetscFunctionReturn(PETSC_SUCCESS); 5538 } 5539 5540 /*@ 5541 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5542 5543 Collective 5544 5545 Input Parameters: 5546 + A - the matrix to test 5547 . B - the matrix to test against, this can equal the first parameter 5548 - tol - tolerance, differences between entries smaller than this are counted as zero 5549 5550 Output Parameter: 5551 . flg - the result 5552 5553 Level: intermediate 5554 5555 Notes: 5556 Only available for `MATAIJ` matrices. 5557 5558 The sequential algorithm 5559 has a running time of the order of the number of nonzeros; the parallel 5560 test involves parallel copies of the block off-diagonal parts of the matrix. 5561 5562 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5563 @*/ 5564 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5565 { 5566 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5567 5568 PetscFunctionBegin; 5569 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5570 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5571 PetscAssertPointer(flg, 4); 5572 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5573 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5574 if (f && g) { 5575 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5576 PetscCall((*f)(A, B, tol, flg)); 5577 } 5578 PetscFunctionReturn(PETSC_SUCCESS); 5579 } 5580 5581 /*@ 5582 MatPermute - Creates a new matrix with rows and columns permuted from the 5583 original. 5584 5585 Collective 5586 5587 Input Parameters: 5588 + mat - the matrix to permute 5589 . row - row permutation, each processor supplies only the permutation for its rows 5590 - col - column permutation, each processor supplies only the permutation for its columns 5591 5592 Output Parameter: 5593 . B - the permuted matrix 5594 5595 Level: advanced 5596 5597 Note: 5598 The index sets map from row/col of permuted matrix to row/col of original matrix. 5599 The index sets should be on the same communicator as mat and have the same local sizes. 5600 5601 Developer Note: 5602 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5603 exploit the fact that row and col are permutations, consider implementing the 5604 more general `MatCreateSubMatrix()` instead. 5605 5606 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5607 @*/ 5608 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5609 { 5610 PetscFunctionBegin; 5611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5612 PetscValidType(mat, 1); 5613 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5614 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5615 PetscAssertPointer(B, 4); 5616 PetscCheckSameComm(mat, 1, row, 2); 5617 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5618 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5619 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5620 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5621 MatCheckPreallocated(mat, 1); 5622 5623 if (mat->ops->permute) { 5624 PetscUseTypeMethod(mat, permute, row, col, B); 5625 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5626 } else { 5627 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5628 } 5629 PetscFunctionReturn(PETSC_SUCCESS); 5630 } 5631 5632 /*@ 5633 MatEqual - Compares two matrices. 5634 5635 Collective 5636 5637 Input Parameters: 5638 + A - the first matrix 5639 - B - the second matrix 5640 5641 Output Parameter: 5642 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5643 5644 Level: intermediate 5645 5646 Note: 5647 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product 5648 using several randomly created vectors, see `MatMultEqual()`. 5649 5650 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5651 @*/ 5652 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5653 { 5654 PetscFunctionBegin; 5655 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5656 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5657 PetscValidType(A, 1); 5658 PetscValidType(B, 2); 5659 PetscAssertPointer(flg, 3); 5660 PetscCheckSameComm(A, 1, B, 2); 5661 MatCheckPreallocated(A, 1); 5662 MatCheckPreallocated(B, 2); 5663 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5664 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5665 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, 5666 B->cmap->N); 5667 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5668 PetscUseTypeMethod(A, equal, B, flg); 5669 } else { 5670 PetscCall(MatMultEqual(A, B, 10, flg)); 5671 } 5672 PetscFunctionReturn(PETSC_SUCCESS); 5673 } 5674 5675 /*@ 5676 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5677 matrices that are stored as vectors. Either of the two scaling 5678 matrices can be `NULL`. 5679 5680 Collective 5681 5682 Input Parameters: 5683 + mat - the matrix to be scaled 5684 . l - the left scaling vector (or `NULL`) 5685 - r - the right scaling vector (or `NULL`) 5686 5687 Level: intermediate 5688 5689 Note: 5690 `MatDiagonalScale()` computes $A = LAR$, where 5691 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5692 The L scales the rows of the matrix, the R scales the columns of the matrix. 5693 5694 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5695 @*/ 5696 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5697 { 5698 PetscFunctionBegin; 5699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5700 PetscValidType(mat, 1); 5701 if (l) { 5702 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5703 PetscCheckSameComm(mat, 1, l, 2); 5704 } 5705 if (r) { 5706 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5707 PetscCheckSameComm(mat, 1, r, 3); 5708 } 5709 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5710 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5711 MatCheckPreallocated(mat, 1); 5712 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5713 5714 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5715 PetscUseTypeMethod(mat, diagonalscale, l, r); 5716 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5717 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5718 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5719 PetscFunctionReturn(PETSC_SUCCESS); 5720 } 5721 5722 /*@ 5723 MatScale - Scales all elements of a matrix by a given number. 5724 5725 Logically Collective 5726 5727 Input Parameters: 5728 + mat - the matrix to be scaled 5729 - a - the scaling value 5730 5731 Level: intermediate 5732 5733 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5734 @*/ 5735 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5736 { 5737 PetscFunctionBegin; 5738 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5739 PetscValidType(mat, 1); 5740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5742 PetscValidLogicalCollectiveScalar(mat, a, 2); 5743 MatCheckPreallocated(mat, 1); 5744 5745 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5746 if (a != (PetscScalar)1.0) { 5747 PetscUseTypeMethod(mat, scale, a); 5748 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5749 } 5750 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5751 PetscFunctionReturn(PETSC_SUCCESS); 5752 } 5753 5754 /*@ 5755 MatNorm - Calculates various norms of a matrix. 5756 5757 Collective 5758 5759 Input Parameters: 5760 + mat - the matrix 5761 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5762 5763 Output Parameter: 5764 . nrm - the resulting norm 5765 5766 Level: intermediate 5767 5768 .seealso: [](ch_matrices), `Mat` 5769 @*/ 5770 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5771 { 5772 PetscFunctionBegin; 5773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5774 PetscValidType(mat, 1); 5775 PetscAssertPointer(nrm, 3); 5776 5777 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5778 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5779 MatCheckPreallocated(mat, 1); 5780 5781 PetscUseTypeMethod(mat, norm, type, nrm); 5782 PetscFunctionReturn(PETSC_SUCCESS); 5783 } 5784 5785 /* 5786 This variable is used to prevent counting of MatAssemblyBegin() that 5787 are called from within a MatAssemblyEnd(). 5788 */ 5789 static PetscInt MatAssemblyEnd_InUse = 0; 5790 /*@ 5791 MatAssemblyBegin - Begins assembling the matrix. This routine should 5792 be called after completing all calls to `MatSetValues()`. 5793 5794 Collective 5795 5796 Input Parameters: 5797 + mat - the matrix 5798 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5799 5800 Level: beginner 5801 5802 Notes: 5803 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5804 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5805 5806 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5807 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5808 using the matrix. 5809 5810 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5811 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 5812 a global collective operation requiring all processes that share the matrix. 5813 5814 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5815 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5816 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5817 5818 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5819 @*/ 5820 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5821 { 5822 PetscFunctionBegin; 5823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5824 PetscValidType(mat, 1); 5825 MatCheckPreallocated(mat, 1); 5826 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5827 if (mat->assembled) { 5828 mat->was_assembled = PETSC_TRUE; 5829 mat->assembled = PETSC_FALSE; 5830 } 5831 5832 if (!MatAssemblyEnd_InUse) { 5833 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5834 PetscTryTypeMethod(mat, assemblybegin, type); 5835 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5836 } else PetscTryTypeMethod(mat, assemblybegin, type); 5837 PetscFunctionReturn(PETSC_SUCCESS); 5838 } 5839 5840 /*@ 5841 MatAssembled - Indicates if a matrix has been assembled and is ready for 5842 use; for example, in matrix-vector product. 5843 5844 Not Collective 5845 5846 Input Parameter: 5847 . mat - the matrix 5848 5849 Output Parameter: 5850 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5851 5852 Level: advanced 5853 5854 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5855 @*/ 5856 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5857 { 5858 PetscFunctionBegin; 5859 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5860 PetscAssertPointer(assembled, 2); 5861 *assembled = mat->assembled; 5862 PetscFunctionReturn(PETSC_SUCCESS); 5863 } 5864 5865 /*@ 5866 MatAssemblyEnd - Completes assembling the matrix. This routine should 5867 be called after `MatAssemblyBegin()`. 5868 5869 Collective 5870 5871 Input Parameters: 5872 + mat - the matrix 5873 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5874 5875 Options Database Keys: 5876 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5877 . -mat_view ::ascii_info_detail - Prints more detailed info 5878 . -mat_view - Prints matrix in ASCII format 5879 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5880 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5881 . -display <name> - Sets display name (default is host) 5882 . -draw_pause <sec> - Sets number of seconds to pause after display 5883 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5884 . -viewer_socket_machine <machine> - Machine to use for socket 5885 . -viewer_socket_port <port> - Port number to use for socket 5886 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5887 5888 Level: beginner 5889 5890 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5891 @*/ 5892 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5893 { 5894 static PetscInt inassm = 0; 5895 PetscBool flg = PETSC_FALSE; 5896 5897 PetscFunctionBegin; 5898 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5899 PetscValidType(mat, 1); 5900 5901 inassm++; 5902 MatAssemblyEnd_InUse++; 5903 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5904 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5905 PetscTryTypeMethod(mat, assemblyend, type); 5906 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5907 } else PetscTryTypeMethod(mat, assemblyend, type); 5908 5909 /* Flush assembly is not a true assembly */ 5910 if (type != MAT_FLUSH_ASSEMBLY) { 5911 if (mat->num_ass) { 5912 if (!mat->symmetry_eternal) { 5913 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5914 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5915 } 5916 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5917 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5918 } 5919 mat->num_ass++; 5920 mat->assembled = PETSC_TRUE; 5921 mat->ass_nonzerostate = mat->nonzerostate; 5922 } 5923 5924 mat->insertmode = NOT_SET_VALUES; 5925 MatAssemblyEnd_InUse--; 5926 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5927 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5928 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5929 5930 if (mat->checksymmetryonassembly) { 5931 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5932 if (flg) { 5933 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5934 } else { 5935 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5936 } 5937 } 5938 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5939 } 5940 inassm--; 5941 PetscFunctionReturn(PETSC_SUCCESS); 5942 } 5943 5944 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5945 /*@ 5946 MatSetOption - Sets a parameter option for a matrix. Some options 5947 may be specific to certain storage formats. Some options 5948 determine how values will be inserted (or added). Sorted, 5949 row-oriented input will generally assemble the fastest. The default 5950 is row-oriented. 5951 5952 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5953 5954 Input Parameters: 5955 + mat - the matrix 5956 . op - the option, one of those listed below (and possibly others), 5957 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5958 5959 Options Describing Matrix Structure: 5960 + `MAT_SPD` - symmetric positive definite 5961 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5962 . `MAT_HERMITIAN` - transpose is the complex conjugation 5963 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5964 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5965 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5966 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5967 5968 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5969 do not need to be computed (usually at a high cost) 5970 5971 Options For Use with `MatSetValues()`: 5972 Insert a logically dense subblock, which can be 5973 . `MAT_ROW_ORIENTED` - row-oriented (default) 5974 5975 These options reflect the data you pass in with `MatSetValues()`; it has 5976 nothing to do with how the data is stored internally in the matrix 5977 data structure. 5978 5979 When (re)assembling a matrix, we can restrict the input for 5980 efficiency/debugging purposes. These options include 5981 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5982 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5983 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5984 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5985 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5986 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5987 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5988 performance for very large process counts. 5989 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5990 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5991 functions, instead sending only neighbor messages. 5992 5993 Level: intermediate 5994 5995 Notes: 5996 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5997 5998 Some options are relevant only for particular matrix types and 5999 are thus ignored by others. Other options are not supported by 6000 certain matrix types and will generate an error message if set. 6001 6002 If using Fortran to compute a matrix, one may need to 6003 use the column-oriented option (or convert to the row-oriented 6004 format). 6005 6006 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6007 that would generate a new entry in the nonzero structure is instead 6008 ignored. Thus, if memory has not already been allocated for this particular 6009 data, then the insertion is ignored. For dense matrices, in which 6010 the entire array is allocated, no entries are ever ignored. 6011 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6012 6013 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6014 that would generate a new entry in the nonzero structure instead produces 6015 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 6016 6017 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6018 that would generate a new entry that has not been preallocated will 6019 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6020 only.) This is a useful flag when debugging matrix memory preallocation. 6021 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6022 6023 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6024 other processors should be dropped, rather than stashed. 6025 This is useful if you know that the "owning" processor is also 6026 always generating the correct matrix entries, so that PETSc need 6027 not transfer duplicate entries generated on another processor. 6028 6029 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6030 searches during matrix assembly. When this flag is set, the hash table 6031 is created during the first matrix assembly. This hash table is 6032 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6033 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6034 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6035 supported by `MATMPIBAIJ` format only. 6036 6037 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6038 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6039 6040 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6041 a zero location in the matrix 6042 6043 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6044 6045 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6046 zero row routines and thus improves performance for very large process counts. 6047 6048 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6049 part of the matrix (since they should match the upper triangular part). 6050 6051 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6052 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6053 with finite difference schemes with non-periodic boundary conditions. 6054 6055 Developer Note: 6056 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6057 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6058 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6059 not changed. 6060 6061 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6062 @*/ 6063 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6064 { 6065 PetscFunctionBegin; 6066 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6067 if (op > 0) { 6068 PetscValidLogicalCollectiveEnum(mat, op, 2); 6069 PetscValidLogicalCollectiveBool(mat, flg, 3); 6070 } 6071 6072 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); 6073 6074 switch (op) { 6075 case MAT_FORCE_DIAGONAL_ENTRIES: 6076 mat->force_diagonals = flg; 6077 PetscFunctionReturn(PETSC_SUCCESS); 6078 case MAT_NO_OFF_PROC_ENTRIES: 6079 mat->nooffprocentries = flg; 6080 PetscFunctionReturn(PETSC_SUCCESS); 6081 case MAT_SUBSET_OFF_PROC_ENTRIES: 6082 mat->assembly_subset = flg; 6083 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6084 #if !defined(PETSC_HAVE_MPIUNI) 6085 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6086 #endif 6087 mat->stash.first_assembly_done = PETSC_FALSE; 6088 } 6089 PetscFunctionReturn(PETSC_SUCCESS); 6090 case MAT_NO_OFF_PROC_ZERO_ROWS: 6091 mat->nooffproczerorows = flg; 6092 PetscFunctionReturn(PETSC_SUCCESS); 6093 case MAT_SPD: 6094 if (flg) { 6095 mat->spd = PETSC_BOOL3_TRUE; 6096 mat->symmetric = PETSC_BOOL3_TRUE; 6097 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6098 } else { 6099 mat->spd = PETSC_BOOL3_FALSE; 6100 } 6101 break; 6102 case MAT_SYMMETRIC: 6103 mat->symmetric = PetscBoolToBool3(flg); 6104 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6105 #if !defined(PETSC_USE_COMPLEX) 6106 mat->hermitian = PetscBoolToBool3(flg); 6107 #endif 6108 break; 6109 case MAT_HERMITIAN: 6110 mat->hermitian = PetscBoolToBool3(flg); 6111 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6112 #if !defined(PETSC_USE_COMPLEX) 6113 mat->symmetric = PetscBoolToBool3(flg); 6114 #endif 6115 break; 6116 case MAT_STRUCTURALLY_SYMMETRIC: 6117 mat->structurally_symmetric = PetscBoolToBool3(flg); 6118 break; 6119 case MAT_SYMMETRY_ETERNAL: 6120 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"); 6121 mat->symmetry_eternal = flg; 6122 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6123 break; 6124 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6125 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"); 6126 mat->structural_symmetry_eternal = flg; 6127 break; 6128 case MAT_SPD_ETERNAL: 6129 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"); 6130 mat->spd_eternal = flg; 6131 if (flg) { 6132 mat->structural_symmetry_eternal = PETSC_TRUE; 6133 mat->symmetry_eternal = PETSC_TRUE; 6134 } 6135 break; 6136 case MAT_STRUCTURE_ONLY: 6137 mat->structure_only = flg; 6138 break; 6139 case MAT_SORTED_FULL: 6140 mat->sortedfull = flg; 6141 break; 6142 default: 6143 break; 6144 } 6145 PetscTryTypeMethod(mat, setoption, op, flg); 6146 PetscFunctionReturn(PETSC_SUCCESS); 6147 } 6148 6149 /*@ 6150 MatGetOption - Gets a parameter option that has been set for a matrix. 6151 6152 Logically Collective 6153 6154 Input Parameters: 6155 + mat - the matrix 6156 - op - the option, this only responds to certain options, check the code for which ones 6157 6158 Output Parameter: 6159 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6160 6161 Level: intermediate 6162 6163 Notes: 6164 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6165 6166 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6167 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6168 6169 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6170 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6171 @*/ 6172 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6173 { 6174 PetscFunctionBegin; 6175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6176 PetscValidType(mat, 1); 6177 6178 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); 6179 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()"); 6180 6181 switch (op) { 6182 case MAT_NO_OFF_PROC_ENTRIES: 6183 *flg = mat->nooffprocentries; 6184 break; 6185 case MAT_NO_OFF_PROC_ZERO_ROWS: 6186 *flg = mat->nooffproczerorows; 6187 break; 6188 case MAT_SYMMETRIC: 6189 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6190 break; 6191 case MAT_HERMITIAN: 6192 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6193 break; 6194 case MAT_STRUCTURALLY_SYMMETRIC: 6195 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6196 break; 6197 case MAT_SPD: 6198 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6199 break; 6200 case MAT_SYMMETRY_ETERNAL: 6201 *flg = mat->symmetry_eternal; 6202 break; 6203 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6204 *flg = mat->symmetry_eternal; 6205 break; 6206 default: 6207 break; 6208 } 6209 PetscFunctionReturn(PETSC_SUCCESS); 6210 } 6211 6212 /*@ 6213 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6214 this routine retains the old nonzero structure. 6215 6216 Logically Collective 6217 6218 Input Parameter: 6219 . mat - the matrix 6220 6221 Level: intermediate 6222 6223 Note: 6224 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. 6225 See the Performance chapter of the users manual for information on preallocating matrices. 6226 6227 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6228 @*/ 6229 PetscErrorCode MatZeroEntries(Mat mat) 6230 { 6231 PetscFunctionBegin; 6232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6233 PetscValidType(mat, 1); 6234 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6235 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"); 6236 MatCheckPreallocated(mat, 1); 6237 6238 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6239 PetscUseTypeMethod(mat, zeroentries); 6240 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6241 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6242 PetscFunctionReturn(PETSC_SUCCESS); 6243 } 6244 6245 /*@ 6246 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6247 of a set of rows and columns of a matrix. 6248 6249 Collective 6250 6251 Input Parameters: 6252 + mat - the matrix 6253 . numRows - the number of rows/columns to zero 6254 . rows - the global row indices 6255 . diag - value put in the diagonal of the eliminated rows 6256 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6257 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6258 6259 Level: intermediate 6260 6261 Notes: 6262 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6263 6264 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6265 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 6266 6267 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6268 Krylov method to take advantage of the known solution on the zeroed rows. 6269 6270 For the parallel case, all processes that share the matrix (i.e., 6271 those in the communicator used for matrix creation) MUST call this 6272 routine, regardless of whether any rows being zeroed are owned by 6273 them. 6274 6275 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6276 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 6277 missing. 6278 6279 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6280 list only rows local to itself). 6281 6282 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6283 6284 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6285 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6286 @*/ 6287 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6288 { 6289 PetscFunctionBegin; 6290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6291 PetscValidType(mat, 1); 6292 if (numRows) PetscAssertPointer(rows, 3); 6293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6294 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6295 MatCheckPreallocated(mat, 1); 6296 6297 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6298 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6299 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6300 PetscFunctionReturn(PETSC_SUCCESS); 6301 } 6302 6303 /*@ 6304 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6305 of a set of rows and columns of a matrix. 6306 6307 Collective 6308 6309 Input Parameters: 6310 + mat - the matrix 6311 . is - the rows to zero 6312 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6313 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6314 - b - optional vector of right-hand side, that will be adjusted by provided solution 6315 6316 Level: intermediate 6317 6318 Note: 6319 See `MatZeroRowsColumns()` for details on how this routine operates. 6320 6321 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6322 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6323 @*/ 6324 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6325 { 6326 PetscInt numRows; 6327 const PetscInt *rows; 6328 6329 PetscFunctionBegin; 6330 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6331 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6332 PetscValidType(mat, 1); 6333 PetscValidType(is, 2); 6334 PetscCall(ISGetLocalSize(is, &numRows)); 6335 PetscCall(ISGetIndices(is, &rows)); 6336 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6337 PetscCall(ISRestoreIndices(is, &rows)); 6338 PetscFunctionReturn(PETSC_SUCCESS); 6339 } 6340 6341 /*@ 6342 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6343 of a set of rows of a matrix. 6344 6345 Collective 6346 6347 Input Parameters: 6348 + mat - the matrix 6349 . numRows - the number of rows to zero 6350 . rows - the global row indices 6351 . diag - value put in the diagonal of the zeroed rows 6352 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6353 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6354 6355 Level: intermediate 6356 6357 Notes: 6358 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6359 6360 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6361 6362 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6363 Krylov method to take advantage of the known solution on the zeroed rows. 6364 6365 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) 6366 from the matrix. 6367 6368 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6369 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6370 formats this does not alter the nonzero structure. 6371 6372 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6373 of the matrix is not changed the values are 6374 merely zeroed. 6375 6376 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6377 formats can optionally remove the main diagonal entry from the 6378 nonzero structure as well, by passing 0.0 as the final argument). 6379 6380 For the parallel case, all processes that share the matrix (i.e., 6381 those in the communicator used for matrix creation) MUST call this 6382 routine, regardless of whether any rows being zeroed are owned by 6383 them. 6384 6385 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6386 list only rows local to itself). 6387 6388 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6389 owns that are to be zeroed. This saves a global synchronization in the implementation. 6390 6391 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6392 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6393 @*/ 6394 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6395 { 6396 PetscFunctionBegin; 6397 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6398 PetscValidType(mat, 1); 6399 if (numRows) PetscAssertPointer(rows, 3); 6400 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6401 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6402 MatCheckPreallocated(mat, 1); 6403 6404 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6405 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6406 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6407 PetscFunctionReturn(PETSC_SUCCESS); 6408 } 6409 6410 /*@ 6411 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6412 of a set of rows of a matrix indicated by an `IS` 6413 6414 Collective 6415 6416 Input Parameters: 6417 + mat - the matrix 6418 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6419 . diag - value put in all diagonals of eliminated rows 6420 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6421 - b - optional vector of right-hand side, that will be adjusted by provided solution 6422 6423 Level: intermediate 6424 6425 Note: 6426 See `MatZeroRows()` for details on how this routine operates. 6427 6428 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6429 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6430 @*/ 6431 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6432 { 6433 PetscInt numRows = 0; 6434 const PetscInt *rows = NULL; 6435 6436 PetscFunctionBegin; 6437 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6438 PetscValidType(mat, 1); 6439 if (is) { 6440 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6441 PetscCall(ISGetLocalSize(is, &numRows)); 6442 PetscCall(ISGetIndices(is, &rows)); 6443 } 6444 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6445 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6446 PetscFunctionReturn(PETSC_SUCCESS); 6447 } 6448 6449 /*@ 6450 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6451 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6452 6453 Collective 6454 6455 Input Parameters: 6456 + mat - the matrix 6457 . numRows - the number of rows to remove 6458 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6459 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6460 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6461 - b - optional vector of right-hand side, that will be adjusted by provided solution 6462 6463 Level: intermediate 6464 6465 Notes: 6466 See `MatZeroRows()` for details on how this routine operates. 6467 6468 The grid coordinates are across the entire grid, not just the local portion 6469 6470 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6471 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6472 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6473 `DM_BOUNDARY_PERIODIC` boundary type. 6474 6475 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 6476 a single value per point) you can skip filling those indices. 6477 6478 Fortran Note: 6479 `idxm` and `idxn` should be declared as 6480 $ MatStencil idxm(4, m) 6481 and the values inserted using 6482 .vb 6483 idxm(MatStencil_i, 1) = i 6484 idxm(MatStencil_j, 1) = j 6485 idxm(MatStencil_k, 1) = k 6486 idxm(MatStencil_c, 1) = c 6487 etc 6488 .ve 6489 6490 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6491 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6492 @*/ 6493 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6494 { 6495 PetscInt dim = mat->stencil.dim; 6496 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6497 PetscInt *dims = mat->stencil.dims + 1; 6498 PetscInt *starts = mat->stencil.starts; 6499 PetscInt *dxm = (PetscInt *)rows; 6500 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6501 6502 PetscFunctionBegin; 6503 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6504 PetscValidType(mat, 1); 6505 if (numRows) PetscAssertPointer(rows, 3); 6506 6507 PetscCall(PetscMalloc1(numRows, &jdxm)); 6508 for (i = 0; i < numRows; ++i) { 6509 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6510 for (j = 0; j < 3 - sdim; ++j) dxm++; 6511 /* Local index in X dir */ 6512 tmp = *dxm++ - starts[0]; 6513 /* Loop over remaining dimensions */ 6514 for (j = 0; j < dim - 1; ++j) { 6515 /* If nonlocal, set index to be negative */ 6516 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6517 /* Update local index */ 6518 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6519 } 6520 /* Skip component slot if necessary */ 6521 if (mat->stencil.noc) dxm++; 6522 /* Local row number */ 6523 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6524 } 6525 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6526 PetscCall(PetscFree(jdxm)); 6527 PetscFunctionReturn(PETSC_SUCCESS); 6528 } 6529 6530 /*@ 6531 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6532 of a set of rows and columns of a matrix. 6533 6534 Collective 6535 6536 Input Parameters: 6537 + mat - the matrix 6538 . numRows - the number of rows/columns to remove 6539 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6540 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6541 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6542 - b - optional vector of right-hand side, that will be adjusted by provided solution 6543 6544 Level: intermediate 6545 6546 Notes: 6547 See `MatZeroRowsColumns()` for details on how this routine operates. 6548 6549 The grid coordinates are across the entire grid, not just the local portion 6550 6551 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6552 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6553 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6554 `DM_BOUNDARY_PERIODIC` boundary type. 6555 6556 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 6557 a single value per point) you can skip filling those indices. 6558 6559 Fortran Note: 6560 `idxm` and `idxn` should be declared as 6561 $ MatStencil idxm(4, m) 6562 and the values inserted using 6563 .vb 6564 idxm(MatStencil_i, 1) = i 6565 idxm(MatStencil_j, 1) = j 6566 idxm(MatStencil_k, 1) = k 6567 idxm(MatStencil_c, 1) = c 6568 etc 6569 .ve 6570 6571 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6572 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6573 @*/ 6574 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6575 { 6576 PetscInt dim = mat->stencil.dim; 6577 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6578 PetscInt *dims = mat->stencil.dims + 1; 6579 PetscInt *starts = mat->stencil.starts; 6580 PetscInt *dxm = (PetscInt *)rows; 6581 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6582 6583 PetscFunctionBegin; 6584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6585 PetscValidType(mat, 1); 6586 if (numRows) PetscAssertPointer(rows, 3); 6587 6588 PetscCall(PetscMalloc1(numRows, &jdxm)); 6589 for (i = 0; i < numRows; ++i) { 6590 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6591 for (j = 0; j < 3 - sdim; ++j) dxm++; 6592 /* Local index in X dir */ 6593 tmp = *dxm++ - starts[0]; 6594 /* Loop over remaining dimensions */ 6595 for (j = 0; j < dim - 1; ++j) { 6596 /* If nonlocal, set index to be negative */ 6597 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6598 /* Update local index */ 6599 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6600 } 6601 /* Skip component slot if necessary */ 6602 if (mat->stencil.noc) dxm++; 6603 /* Local row number */ 6604 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6605 } 6606 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6607 PetscCall(PetscFree(jdxm)); 6608 PetscFunctionReturn(PETSC_SUCCESS); 6609 } 6610 6611 /*@ 6612 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6613 of a set of rows of a matrix; using local numbering of rows. 6614 6615 Collective 6616 6617 Input Parameters: 6618 + mat - the matrix 6619 . numRows - the number of rows to remove 6620 . rows - the local row indices 6621 . diag - value put in all diagonals of eliminated rows 6622 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6623 - b - optional vector of right-hand side, that will be adjusted by provided solution 6624 6625 Level: intermediate 6626 6627 Notes: 6628 Before calling `MatZeroRowsLocal()`, the user must first set the 6629 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6630 6631 See `MatZeroRows()` for details on how this routine operates. 6632 6633 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6634 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6635 @*/ 6636 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6637 { 6638 PetscFunctionBegin; 6639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6640 PetscValidType(mat, 1); 6641 if (numRows) PetscAssertPointer(rows, 3); 6642 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6643 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6644 MatCheckPreallocated(mat, 1); 6645 6646 if (mat->ops->zerorowslocal) { 6647 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6648 } else { 6649 IS is, newis; 6650 const PetscInt *newRows; 6651 6652 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6653 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6654 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6655 PetscCall(ISGetIndices(newis, &newRows)); 6656 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6657 PetscCall(ISRestoreIndices(newis, &newRows)); 6658 PetscCall(ISDestroy(&newis)); 6659 PetscCall(ISDestroy(&is)); 6660 } 6661 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6662 PetscFunctionReturn(PETSC_SUCCESS); 6663 } 6664 6665 /*@ 6666 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6667 of a set of rows of a matrix; using local numbering of rows. 6668 6669 Collective 6670 6671 Input Parameters: 6672 + mat - the matrix 6673 . is - index set of rows to remove 6674 . diag - value put in all diagonals of eliminated rows 6675 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6676 - b - optional vector of right-hand side, that will be adjusted by provided solution 6677 6678 Level: intermediate 6679 6680 Notes: 6681 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6682 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6683 6684 See `MatZeroRows()` for details on how this routine operates. 6685 6686 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6687 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6688 @*/ 6689 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6690 { 6691 PetscInt numRows; 6692 const PetscInt *rows; 6693 6694 PetscFunctionBegin; 6695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6696 PetscValidType(mat, 1); 6697 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6698 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6699 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6700 MatCheckPreallocated(mat, 1); 6701 6702 PetscCall(ISGetLocalSize(is, &numRows)); 6703 PetscCall(ISGetIndices(is, &rows)); 6704 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6705 PetscCall(ISRestoreIndices(is, &rows)); 6706 PetscFunctionReturn(PETSC_SUCCESS); 6707 } 6708 6709 /*@ 6710 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6711 of a set of rows and columns of a matrix; using local numbering of rows. 6712 6713 Collective 6714 6715 Input Parameters: 6716 + mat - the matrix 6717 . numRows - the number of rows to remove 6718 . rows - the global row indices 6719 . diag - value put in all diagonals of eliminated rows 6720 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6721 - b - optional vector of right-hand side, that will be adjusted by provided solution 6722 6723 Level: intermediate 6724 6725 Notes: 6726 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6727 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6728 6729 See `MatZeroRowsColumns()` for details on how this routine operates. 6730 6731 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6732 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6733 @*/ 6734 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6735 { 6736 IS is, newis; 6737 const PetscInt *newRows; 6738 6739 PetscFunctionBegin; 6740 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6741 PetscValidType(mat, 1); 6742 if (numRows) PetscAssertPointer(rows, 3); 6743 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6744 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6745 MatCheckPreallocated(mat, 1); 6746 6747 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6748 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6749 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6750 PetscCall(ISGetIndices(newis, &newRows)); 6751 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6752 PetscCall(ISRestoreIndices(newis, &newRows)); 6753 PetscCall(ISDestroy(&newis)); 6754 PetscCall(ISDestroy(&is)); 6755 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6756 PetscFunctionReturn(PETSC_SUCCESS); 6757 } 6758 6759 /*@ 6760 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6761 of a set of rows and columns of a matrix; using local numbering of rows. 6762 6763 Collective 6764 6765 Input Parameters: 6766 + mat - the matrix 6767 . is - index set of rows to remove 6768 . diag - value put in all diagonals of eliminated rows 6769 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6770 - b - optional vector of right-hand side, that will be adjusted by provided solution 6771 6772 Level: intermediate 6773 6774 Notes: 6775 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6776 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6777 6778 See `MatZeroRowsColumns()` for details on how this routine operates. 6779 6780 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6781 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6782 @*/ 6783 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6784 { 6785 PetscInt numRows; 6786 const PetscInt *rows; 6787 6788 PetscFunctionBegin; 6789 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6790 PetscValidType(mat, 1); 6791 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6792 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6793 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6794 MatCheckPreallocated(mat, 1); 6795 6796 PetscCall(ISGetLocalSize(is, &numRows)); 6797 PetscCall(ISGetIndices(is, &rows)); 6798 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6799 PetscCall(ISRestoreIndices(is, &rows)); 6800 PetscFunctionReturn(PETSC_SUCCESS); 6801 } 6802 6803 /*@ 6804 MatGetSize - Returns the numbers of rows and columns in a matrix. 6805 6806 Not Collective 6807 6808 Input Parameter: 6809 . mat - the matrix 6810 6811 Output Parameters: 6812 + m - the number of global rows 6813 - n - the number of global columns 6814 6815 Level: beginner 6816 6817 Note: 6818 Both output parameters can be `NULL` on input. 6819 6820 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6821 @*/ 6822 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6823 { 6824 PetscFunctionBegin; 6825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6826 if (m) *m = mat->rmap->N; 6827 if (n) *n = mat->cmap->N; 6828 PetscFunctionReturn(PETSC_SUCCESS); 6829 } 6830 6831 /*@ 6832 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6833 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6834 6835 Not Collective 6836 6837 Input Parameter: 6838 . mat - the matrix 6839 6840 Output Parameters: 6841 + m - the number of local rows, use `NULL` to not obtain this value 6842 - n - the number of local columns, use `NULL` to not obtain this value 6843 6844 Level: beginner 6845 6846 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6847 @*/ 6848 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6849 { 6850 PetscFunctionBegin; 6851 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6852 if (m) PetscAssertPointer(m, 2); 6853 if (n) PetscAssertPointer(n, 3); 6854 if (m) *m = mat->rmap->n; 6855 if (n) *n = mat->cmap->n; 6856 PetscFunctionReturn(PETSC_SUCCESS); 6857 } 6858 6859 /*@ 6860 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6861 vector one multiplies this matrix by that are owned by this processor. 6862 6863 Not Collective, unless matrix has not been allocated, then collective 6864 6865 Input Parameter: 6866 . mat - the matrix 6867 6868 Output Parameters: 6869 + m - the global index of the first local column, use `NULL` to not obtain this value 6870 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6871 6872 Level: developer 6873 6874 Notes: 6875 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6876 6877 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6878 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6879 6880 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6881 the local values in the matrix. 6882 6883 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6884 Layouts](sec_matlayout) for details on matrix layouts. 6885 6886 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6887 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6888 @*/ 6889 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6890 { 6891 PetscFunctionBegin; 6892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6893 PetscValidType(mat, 1); 6894 if (m) PetscAssertPointer(m, 2); 6895 if (n) PetscAssertPointer(n, 3); 6896 MatCheckPreallocated(mat, 1); 6897 if (m) *m = mat->cmap->rstart; 6898 if (n) *n = mat->cmap->rend; 6899 PetscFunctionReturn(PETSC_SUCCESS); 6900 } 6901 6902 /*@ 6903 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6904 this MPI process. 6905 6906 Not Collective 6907 6908 Input Parameter: 6909 . mat - the matrix 6910 6911 Output Parameters: 6912 + m - the global index of the first local row, use `NULL` to not obtain this value 6913 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6914 6915 Level: beginner 6916 6917 Notes: 6918 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6919 6920 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6921 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6922 6923 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6924 the local values in the matrix. 6925 6926 The high argument is one more than the last element stored locally. 6927 6928 For all matrices it returns the range of matrix rows associated with rows of a vector that 6929 would contain the result of a matrix vector product with this matrix. See [Matrix 6930 Layouts](sec_matlayout) for details on matrix layouts. 6931 6932 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6933 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6934 @*/ 6935 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6936 { 6937 PetscFunctionBegin; 6938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6939 PetscValidType(mat, 1); 6940 if (m) PetscAssertPointer(m, 2); 6941 if (n) PetscAssertPointer(n, 3); 6942 MatCheckPreallocated(mat, 1); 6943 if (m) *m = mat->rmap->rstart; 6944 if (n) *n = mat->rmap->rend; 6945 PetscFunctionReturn(PETSC_SUCCESS); 6946 } 6947 6948 /*@C 6949 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6950 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6951 6952 Not Collective, unless matrix has not been allocated 6953 6954 Input Parameter: 6955 . mat - the matrix 6956 6957 Output Parameter: 6958 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6959 where `size` is the number of MPI processes used by `mat` 6960 6961 Level: beginner 6962 6963 Notes: 6964 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6965 6966 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6967 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6968 6969 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6970 the local values in the matrix. 6971 6972 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6973 would contain the result of a matrix vector product with this matrix. See [Matrix 6974 Layouts](sec_matlayout) for details on matrix layouts. 6975 6976 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6977 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6978 `DMDAGetGhostCorners()`, `DM` 6979 @*/ 6980 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6981 { 6982 PetscFunctionBegin; 6983 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6984 PetscValidType(mat, 1); 6985 MatCheckPreallocated(mat, 1); 6986 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6987 PetscFunctionReturn(PETSC_SUCCESS); 6988 } 6989 6990 /*@C 6991 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6992 vector one multiplies this vector by that are owned by each processor. 6993 6994 Not Collective, unless matrix has not been allocated 6995 6996 Input Parameter: 6997 . mat - the matrix 6998 6999 Output Parameter: 7000 . ranges - start of each processors portion plus one more than the total length at the end 7001 7002 Level: beginner 7003 7004 Notes: 7005 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7006 7007 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7008 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7009 7010 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7011 the local values in the matrix. 7012 7013 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7014 Layouts](sec_matlayout) for details on matrix layouts. 7015 7016 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7017 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7018 `DMDAGetGhostCorners()`, `DM` 7019 @*/ 7020 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7021 { 7022 PetscFunctionBegin; 7023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7024 PetscValidType(mat, 1); 7025 MatCheckPreallocated(mat, 1); 7026 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7027 PetscFunctionReturn(PETSC_SUCCESS); 7028 } 7029 7030 /*@ 7031 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7032 7033 Not Collective 7034 7035 Input Parameter: 7036 . A - matrix 7037 7038 Output Parameters: 7039 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7040 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7041 7042 Level: intermediate 7043 7044 Note: 7045 You should call `ISDestroy()` on the returned `IS` 7046 7047 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7048 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7049 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7050 details on matrix layouts. 7051 7052 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7053 @*/ 7054 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7055 { 7056 PetscErrorCode (*f)(Mat, IS *, IS *); 7057 7058 PetscFunctionBegin; 7059 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7060 PetscValidType(A, 1); 7061 MatCheckPreallocated(A, 1); 7062 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7063 if (f) { 7064 PetscCall((*f)(A, rows, cols)); 7065 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7066 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7067 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7068 } 7069 PetscFunctionReturn(PETSC_SUCCESS); 7070 } 7071 7072 /*@ 7073 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7074 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7075 to complete the factorization. 7076 7077 Collective 7078 7079 Input Parameters: 7080 + fact - the factorized matrix obtained with `MatGetFactor()` 7081 . mat - the matrix 7082 . row - row permutation 7083 . col - column permutation 7084 - info - structure containing 7085 .vb 7086 levels - number of levels of fill. 7087 expected fill - as ratio of original fill. 7088 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7089 missing diagonal entries) 7090 .ve 7091 7092 Level: developer 7093 7094 Notes: 7095 See [Matrix Factorization](sec_matfactor) for additional information. 7096 7097 Most users should employ the `KSP` interface for linear solvers 7098 instead of working directly with matrix algebra routines such as this. 7099 See, e.g., `KSPCreate()`. 7100 7101 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7102 7103 Developer Note: 7104 The Fortran interface is not autogenerated as the 7105 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7106 7107 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7108 `MatGetOrdering()`, `MatFactorInfo` 7109 @*/ 7110 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7111 { 7112 PetscFunctionBegin; 7113 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7114 PetscValidType(mat, 2); 7115 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7116 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7117 PetscAssertPointer(info, 5); 7118 PetscAssertPointer(fact, 1); 7119 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7120 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7121 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7122 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7123 MatCheckPreallocated(mat, 2); 7124 7125 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7126 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7127 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7128 PetscFunctionReturn(PETSC_SUCCESS); 7129 } 7130 7131 /*@ 7132 MatICCFactorSymbolic - Performs symbolic incomplete 7133 Cholesky factorization for a symmetric matrix. Use 7134 `MatCholeskyFactorNumeric()` to complete the factorization. 7135 7136 Collective 7137 7138 Input Parameters: 7139 + fact - the factorized matrix obtained with `MatGetFactor()` 7140 . mat - the matrix to be factored 7141 . perm - row and column permutation 7142 - info - structure containing 7143 .vb 7144 levels - number of levels of fill. 7145 expected fill - as ratio of original fill. 7146 .ve 7147 7148 Level: developer 7149 7150 Notes: 7151 Most users should employ the `KSP` interface for linear solvers 7152 instead of working directly with matrix algebra routines such as this. 7153 See, e.g., `KSPCreate()`. 7154 7155 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7156 7157 Developer Note: 7158 The Fortran interface is not autogenerated as the 7159 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7160 7161 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7162 @*/ 7163 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7164 { 7165 PetscFunctionBegin; 7166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7167 PetscValidType(mat, 2); 7168 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7169 PetscAssertPointer(info, 4); 7170 PetscAssertPointer(fact, 1); 7171 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7172 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7173 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7174 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7175 MatCheckPreallocated(mat, 2); 7176 7177 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7178 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7179 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7180 PetscFunctionReturn(PETSC_SUCCESS); 7181 } 7182 7183 /*@C 7184 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7185 points to an array of valid matrices, they may be reused to store the new 7186 submatrices. 7187 7188 Collective 7189 7190 Input Parameters: 7191 + mat - the matrix 7192 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7193 . irow - index set of rows to extract 7194 . icol - index set of columns to extract 7195 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7196 7197 Output Parameter: 7198 . submat - the array of submatrices 7199 7200 Level: advanced 7201 7202 Notes: 7203 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7204 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7205 to extract a parallel submatrix. 7206 7207 Some matrix types place restrictions on the row and column 7208 indices, such as that they be sorted or that they be equal to each other. 7209 7210 The index sets may not have duplicate entries. 7211 7212 When extracting submatrices from a parallel matrix, each processor can 7213 form a different submatrix by setting the rows and columns of its 7214 individual index sets according to the local submatrix desired. 7215 7216 When finished using the submatrices, the user should destroy 7217 them with `MatDestroySubMatrices()`. 7218 7219 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7220 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7221 7222 This routine creates the matrices in submat; you should NOT create them before 7223 calling it. It also allocates the array of matrix pointers submat. 7224 7225 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7226 request one row/column in a block, they must request all rows/columns that are in 7227 that block. For example, if the block size is 2 you cannot request just row 0 and 7228 column 0. 7229 7230 Fortran Note: 7231 .vb 7232 Mat, pointer :: submat(:) 7233 .ve 7234 7235 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7236 @*/ 7237 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7238 { 7239 PetscInt i; 7240 PetscBool eq; 7241 7242 PetscFunctionBegin; 7243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7244 PetscValidType(mat, 1); 7245 if (n) { 7246 PetscAssertPointer(irow, 3); 7247 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7248 PetscAssertPointer(icol, 4); 7249 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7250 } 7251 PetscAssertPointer(submat, 6); 7252 if (n && scall == MAT_REUSE_MATRIX) { 7253 PetscAssertPointer(*submat, 6); 7254 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7255 } 7256 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7257 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7258 MatCheckPreallocated(mat, 1); 7259 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7260 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7261 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7262 for (i = 0; i < n; i++) { 7263 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7264 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7265 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7266 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7267 if (mat->boundtocpu && mat->bindingpropagates) { 7268 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7269 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7270 } 7271 #endif 7272 } 7273 PetscFunctionReturn(PETSC_SUCCESS); 7274 } 7275 7276 /*@C 7277 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7278 7279 Collective 7280 7281 Input Parameters: 7282 + mat - the matrix 7283 . n - the number of submatrixes to be extracted 7284 . irow - index set of rows to extract 7285 . icol - index set of columns to extract 7286 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7287 7288 Output Parameter: 7289 . submat - the array of submatrices 7290 7291 Level: advanced 7292 7293 Note: 7294 This is used by `PCGASM` 7295 7296 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7297 @*/ 7298 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7299 { 7300 PetscInt i; 7301 PetscBool eq; 7302 7303 PetscFunctionBegin; 7304 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7305 PetscValidType(mat, 1); 7306 if (n) { 7307 PetscAssertPointer(irow, 3); 7308 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7309 PetscAssertPointer(icol, 4); 7310 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7311 } 7312 PetscAssertPointer(submat, 6); 7313 if (n && scall == MAT_REUSE_MATRIX) { 7314 PetscAssertPointer(*submat, 6); 7315 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7316 } 7317 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7318 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7319 MatCheckPreallocated(mat, 1); 7320 7321 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7322 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7323 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7324 for (i = 0; i < n; i++) { 7325 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7326 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7327 } 7328 PetscFunctionReturn(PETSC_SUCCESS); 7329 } 7330 7331 /*@C 7332 MatDestroyMatrices - Destroys an array of matrices 7333 7334 Collective 7335 7336 Input Parameters: 7337 + n - the number of local matrices 7338 - mat - the matrices (this is a pointer to the array of matrices) 7339 7340 Level: advanced 7341 7342 Notes: 7343 Frees not only the matrices, but also the array that contains the matrices 7344 7345 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7346 7347 Fortran Note: 7348 Does not free the `mat` array. 7349 7350 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7351 @*/ 7352 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7353 { 7354 PetscInt i; 7355 7356 PetscFunctionBegin; 7357 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7358 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7359 PetscAssertPointer(mat, 2); 7360 7361 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7362 7363 /* memory is allocated even if n = 0 */ 7364 PetscCall(PetscFree(*mat)); 7365 PetscFunctionReturn(PETSC_SUCCESS); 7366 } 7367 7368 /*@C 7369 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7370 7371 Collective 7372 7373 Input Parameters: 7374 + n - the number of local matrices 7375 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7376 7377 Level: advanced 7378 7379 Note: 7380 Frees not only the matrices, but also the array that contains the matrices 7381 7382 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7383 @*/ 7384 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7385 { 7386 Mat mat0; 7387 7388 PetscFunctionBegin; 7389 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7390 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7391 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7392 PetscAssertPointer(mat, 2); 7393 7394 mat0 = (*mat)[0]; 7395 if (mat0 && mat0->ops->destroysubmatrices) { 7396 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7397 } else { 7398 PetscCall(MatDestroyMatrices(n, mat)); 7399 } 7400 PetscFunctionReturn(PETSC_SUCCESS); 7401 } 7402 7403 /*@ 7404 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7405 7406 Collective 7407 7408 Input Parameter: 7409 . mat - the matrix 7410 7411 Output Parameter: 7412 . matstruct - the sequential matrix with the nonzero structure of `mat` 7413 7414 Level: developer 7415 7416 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7417 @*/ 7418 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7419 { 7420 PetscFunctionBegin; 7421 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7422 PetscAssertPointer(matstruct, 2); 7423 7424 PetscValidType(mat, 1); 7425 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7426 MatCheckPreallocated(mat, 1); 7427 7428 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7429 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7430 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7431 PetscFunctionReturn(PETSC_SUCCESS); 7432 } 7433 7434 /*@C 7435 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7436 7437 Collective 7438 7439 Input Parameter: 7440 . mat - the matrix 7441 7442 Level: advanced 7443 7444 Note: 7445 This is not needed, one can just call `MatDestroy()` 7446 7447 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7448 @*/ 7449 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7450 { 7451 PetscFunctionBegin; 7452 PetscAssertPointer(mat, 1); 7453 PetscCall(MatDestroy(mat)); 7454 PetscFunctionReturn(PETSC_SUCCESS); 7455 } 7456 7457 /*@ 7458 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7459 replaces the index sets by larger ones that represent submatrices with 7460 additional overlap. 7461 7462 Collective 7463 7464 Input Parameters: 7465 + mat - the matrix 7466 . n - the number of index sets 7467 . is - the array of index sets (these index sets will changed during the call) 7468 - ov - the additional overlap requested 7469 7470 Options Database Key: 7471 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7472 7473 Level: developer 7474 7475 Note: 7476 The computed overlap preserves the matrix block sizes when the blocks are square. 7477 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7478 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7479 7480 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7481 @*/ 7482 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7483 { 7484 PetscInt i, bs, cbs; 7485 7486 PetscFunctionBegin; 7487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7488 PetscValidType(mat, 1); 7489 PetscValidLogicalCollectiveInt(mat, n, 2); 7490 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7491 if (n) { 7492 PetscAssertPointer(is, 3); 7493 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7494 } 7495 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7496 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7497 MatCheckPreallocated(mat, 1); 7498 7499 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7500 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7501 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7502 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7503 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7504 if (bs == cbs) { 7505 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7506 } 7507 PetscFunctionReturn(PETSC_SUCCESS); 7508 } 7509 7510 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7511 7512 /*@ 7513 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7514 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7515 additional overlap. 7516 7517 Collective 7518 7519 Input Parameters: 7520 + mat - the matrix 7521 . n - the number of index sets 7522 . is - the array of index sets (these index sets will changed during the call) 7523 - ov - the additional overlap requested 7524 7525 ` Options Database Key: 7526 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7527 7528 Level: developer 7529 7530 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7531 @*/ 7532 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7533 { 7534 PetscInt i; 7535 7536 PetscFunctionBegin; 7537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7538 PetscValidType(mat, 1); 7539 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7540 if (n) { 7541 PetscAssertPointer(is, 3); 7542 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7543 } 7544 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7545 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7546 MatCheckPreallocated(mat, 1); 7547 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7548 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7549 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7550 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7551 PetscFunctionReturn(PETSC_SUCCESS); 7552 } 7553 7554 /*@ 7555 MatGetBlockSize - Returns the matrix block size. 7556 7557 Not Collective 7558 7559 Input Parameter: 7560 . mat - the matrix 7561 7562 Output Parameter: 7563 . bs - block size 7564 7565 Level: intermediate 7566 7567 Notes: 7568 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7569 7570 If the block size has not been set yet this routine returns 1. 7571 7572 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7573 @*/ 7574 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7575 { 7576 PetscFunctionBegin; 7577 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7578 PetscAssertPointer(bs, 2); 7579 *bs = mat->rmap->bs; 7580 PetscFunctionReturn(PETSC_SUCCESS); 7581 } 7582 7583 /*@ 7584 MatGetBlockSizes - Returns the matrix block row and column sizes. 7585 7586 Not Collective 7587 7588 Input Parameter: 7589 . mat - the matrix 7590 7591 Output Parameters: 7592 + rbs - row block size 7593 - cbs - column block size 7594 7595 Level: intermediate 7596 7597 Notes: 7598 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7599 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7600 7601 If a block size has not been set yet this routine returns 1. 7602 7603 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7604 @*/ 7605 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7606 { 7607 PetscFunctionBegin; 7608 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7609 if (rbs) PetscAssertPointer(rbs, 2); 7610 if (cbs) PetscAssertPointer(cbs, 3); 7611 if (rbs) *rbs = mat->rmap->bs; 7612 if (cbs) *cbs = mat->cmap->bs; 7613 PetscFunctionReturn(PETSC_SUCCESS); 7614 } 7615 7616 /*@ 7617 MatSetBlockSize - Sets the matrix block size. 7618 7619 Logically Collective 7620 7621 Input Parameters: 7622 + mat - the matrix 7623 - bs - block size 7624 7625 Level: intermediate 7626 7627 Notes: 7628 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7629 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7630 7631 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7632 is compatible with the matrix local sizes. 7633 7634 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7635 @*/ 7636 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7637 { 7638 PetscFunctionBegin; 7639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7640 PetscValidLogicalCollectiveInt(mat, bs, 2); 7641 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7642 PetscFunctionReturn(PETSC_SUCCESS); 7643 } 7644 7645 typedef struct { 7646 PetscInt n; 7647 IS *is; 7648 Mat *mat; 7649 PetscObjectState nonzerostate; 7650 Mat C; 7651 } EnvelopeData; 7652 7653 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7654 { 7655 EnvelopeData *edata = (EnvelopeData *)*ptr; 7656 7657 PetscFunctionBegin; 7658 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7659 PetscCall(PetscFree(edata->is)); 7660 PetscCall(PetscFree(edata)); 7661 PetscFunctionReturn(PETSC_SUCCESS); 7662 } 7663 7664 /*@ 7665 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7666 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7667 7668 Collective 7669 7670 Input Parameter: 7671 . mat - the matrix 7672 7673 Level: intermediate 7674 7675 Notes: 7676 There can be zeros within the blocks 7677 7678 The blocks can overlap between processes, including laying on more than two processes 7679 7680 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7681 @*/ 7682 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7683 { 7684 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7685 PetscInt *diag, *odiag, sc; 7686 VecScatter scatter; 7687 PetscScalar *seqv; 7688 const PetscScalar *parv; 7689 const PetscInt *ia, *ja; 7690 PetscBool set, flag, done; 7691 Mat AA = mat, A; 7692 MPI_Comm comm; 7693 PetscMPIInt rank, size, tag; 7694 MPI_Status status; 7695 PetscContainer container; 7696 EnvelopeData *edata; 7697 Vec seq, par; 7698 IS isglobal; 7699 7700 PetscFunctionBegin; 7701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7702 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7703 if (!set || !flag) { 7704 /* TODO: only needs nonzero structure of transpose */ 7705 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7706 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7707 } 7708 PetscCall(MatAIJGetLocalMat(AA, &A)); 7709 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7710 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7711 7712 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7713 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7714 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7715 PetscCallMPI(MPI_Comm_size(comm, &size)); 7716 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7717 7718 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7719 7720 if (rank > 0) { 7721 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7722 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7723 } 7724 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7725 for (i = 0; i < n; i++) { 7726 env = PetscMax(env, ja[ia[i + 1] - 1]); 7727 II = rstart + i; 7728 if (env == II) { 7729 starts[lblocks] = tbs; 7730 sizes[lblocks++] = 1 + II - tbs; 7731 tbs = 1 + II; 7732 } 7733 } 7734 if (rank < size - 1) { 7735 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7736 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7737 } 7738 7739 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7740 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7741 PetscCall(MatDestroy(&A)); 7742 7743 PetscCall(PetscNew(&edata)); 7744 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7745 edata->n = lblocks; 7746 /* create IS needed for extracting blocks from the original matrix */ 7747 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7748 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7749 7750 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7751 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7752 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7753 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7754 PetscCall(MatSetType(edata->C, MATAIJ)); 7755 7756 /* Communicate the start and end of each row, from each block to the correct rank */ 7757 /* TODO: Use PetscSF instead of VecScatter */ 7758 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7759 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7760 PetscCall(VecGetArrayWrite(seq, &seqv)); 7761 for (PetscInt i = 0; i < lblocks; i++) { 7762 for (PetscInt j = 0; j < sizes[i]; j++) { 7763 seqv[cnt] = starts[i]; 7764 seqv[cnt + 1] = starts[i] + sizes[i]; 7765 cnt += 2; 7766 } 7767 } 7768 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7769 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7770 sc -= cnt; 7771 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7772 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7773 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7774 PetscCall(ISDestroy(&isglobal)); 7775 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7776 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7777 PetscCall(VecScatterDestroy(&scatter)); 7778 PetscCall(VecDestroy(&seq)); 7779 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7780 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7781 PetscCall(VecGetArrayRead(par, &parv)); 7782 cnt = 0; 7783 PetscCall(MatGetSize(mat, NULL, &n)); 7784 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7785 PetscInt start, end, d = 0, od = 0; 7786 7787 start = (PetscInt)PetscRealPart(parv[cnt]); 7788 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7789 cnt += 2; 7790 7791 if (start < cstart) { 7792 od += cstart - start + n - cend; 7793 d += cend - cstart; 7794 } else if (start < cend) { 7795 od += n - cend; 7796 d += cend - start; 7797 } else od += n - start; 7798 if (end <= cstart) { 7799 od -= cstart - end + n - cend; 7800 d -= cend - cstart; 7801 } else if (end < cend) { 7802 od -= n - cend; 7803 d -= cend - end; 7804 } else od -= n - end; 7805 7806 odiag[i] = od; 7807 diag[i] = d; 7808 } 7809 PetscCall(VecRestoreArrayRead(par, &parv)); 7810 PetscCall(VecDestroy(&par)); 7811 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7812 PetscCall(PetscFree2(diag, odiag)); 7813 PetscCall(PetscFree2(sizes, starts)); 7814 7815 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7816 PetscCall(PetscContainerSetPointer(container, edata)); 7817 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7818 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7819 PetscCall(PetscObjectDereference((PetscObject)container)); 7820 PetscFunctionReturn(PETSC_SUCCESS); 7821 } 7822 7823 /*@ 7824 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7825 7826 Collective 7827 7828 Input Parameters: 7829 + A - the matrix 7830 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7831 7832 Output Parameter: 7833 . C - matrix with inverted block diagonal of `A` 7834 7835 Level: advanced 7836 7837 Note: 7838 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7839 7840 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7841 @*/ 7842 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7843 { 7844 PetscContainer container; 7845 EnvelopeData *edata; 7846 PetscObjectState nonzerostate; 7847 7848 PetscFunctionBegin; 7849 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7850 if (!container) { 7851 PetscCall(MatComputeVariableBlockEnvelope(A)); 7852 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7853 } 7854 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7855 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7856 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7857 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7858 7859 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7860 *C = edata->C; 7861 7862 for (PetscInt i = 0; i < edata->n; i++) { 7863 Mat D; 7864 PetscScalar *dvalues; 7865 7866 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7867 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7868 PetscCall(MatSeqDenseInvert(D)); 7869 PetscCall(MatDenseGetArray(D, &dvalues)); 7870 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7871 PetscCall(MatDestroy(&D)); 7872 } 7873 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7874 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7875 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7876 PetscFunctionReturn(PETSC_SUCCESS); 7877 } 7878 7879 /*@ 7880 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7881 7882 Not Collective 7883 7884 Input Parameters: 7885 + mat - the matrix 7886 . nblocks - the number of blocks on this process, each block can only exist on a single process 7887 - bsizes - the block sizes 7888 7889 Level: intermediate 7890 7891 Notes: 7892 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7893 7894 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. 7895 7896 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7897 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7898 @*/ 7899 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7900 { 7901 PetscInt ncnt = 0, nlocal; 7902 7903 PetscFunctionBegin; 7904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7905 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7906 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); 7907 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7908 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); 7909 PetscCall(PetscFree(mat->bsizes)); 7910 mat->nblocks = nblocks; 7911 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7912 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7913 PetscFunctionReturn(PETSC_SUCCESS); 7914 } 7915 7916 /*@C 7917 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7918 7919 Not Collective; No Fortran Support 7920 7921 Input Parameter: 7922 . mat - the matrix 7923 7924 Output Parameters: 7925 + nblocks - the number of blocks on this process 7926 - bsizes - the block sizes 7927 7928 Level: intermediate 7929 7930 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7931 @*/ 7932 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7933 { 7934 PetscFunctionBegin; 7935 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7936 if (nblocks) *nblocks = mat->nblocks; 7937 if (bsizes) *bsizes = mat->bsizes; 7938 PetscFunctionReturn(PETSC_SUCCESS); 7939 } 7940 7941 /*@ 7942 MatSetBlockSizes - Sets the matrix block row and column sizes. 7943 7944 Logically Collective 7945 7946 Input Parameters: 7947 + mat - the matrix 7948 . rbs - row block size 7949 - cbs - column block size 7950 7951 Level: intermediate 7952 7953 Notes: 7954 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7955 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7956 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7957 7958 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7959 are compatible with the matrix local sizes. 7960 7961 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7962 7963 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7964 @*/ 7965 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7966 { 7967 PetscFunctionBegin; 7968 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7969 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7970 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7971 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7972 if (mat->rmap->refcnt) { 7973 ISLocalToGlobalMapping l2g = NULL; 7974 PetscLayout nmap = NULL; 7975 7976 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7977 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7978 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7979 mat->rmap = nmap; 7980 mat->rmap->mapping = l2g; 7981 } 7982 if (mat->cmap->refcnt) { 7983 ISLocalToGlobalMapping l2g = NULL; 7984 PetscLayout nmap = NULL; 7985 7986 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7987 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7988 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7989 mat->cmap = nmap; 7990 mat->cmap->mapping = l2g; 7991 } 7992 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7993 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7994 PetscFunctionReturn(PETSC_SUCCESS); 7995 } 7996 7997 /*@ 7998 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7999 8000 Logically Collective 8001 8002 Input Parameters: 8003 + mat - the matrix 8004 . fromRow - matrix from which to copy row block size 8005 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8006 8007 Level: developer 8008 8009 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8010 @*/ 8011 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8012 { 8013 PetscFunctionBegin; 8014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8015 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8016 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8017 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8018 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8019 PetscFunctionReturn(PETSC_SUCCESS); 8020 } 8021 8022 /*@ 8023 MatResidual - Default routine to calculate the residual r = b - Ax 8024 8025 Collective 8026 8027 Input Parameters: 8028 + mat - the matrix 8029 . b - the right-hand-side 8030 - x - the approximate solution 8031 8032 Output Parameter: 8033 . r - location to store the residual 8034 8035 Level: developer 8036 8037 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8038 @*/ 8039 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8040 { 8041 PetscFunctionBegin; 8042 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8043 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8044 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8045 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8046 PetscValidType(mat, 1); 8047 MatCheckPreallocated(mat, 1); 8048 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8049 if (!mat->ops->residual) { 8050 PetscCall(MatMult(mat, x, r)); 8051 PetscCall(VecAYPX(r, -1.0, b)); 8052 } else { 8053 PetscUseTypeMethod(mat, residual, b, x, r); 8054 } 8055 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8056 PetscFunctionReturn(PETSC_SUCCESS); 8057 } 8058 8059 /*@C 8060 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8061 8062 Collective 8063 8064 Input Parameters: 8065 + mat - the matrix 8066 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8067 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8068 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8069 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8070 always used. 8071 8072 Output Parameters: 8073 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8074 . 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 8075 . ja - the column indices, use `NULL` if not needed 8076 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8077 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8078 8079 Level: developer 8080 8081 Notes: 8082 You CANNOT change any of the ia[] or ja[] values. 8083 8084 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8085 8086 Fortran Notes: 8087 Use 8088 .vb 8089 PetscInt, pointer :: ia(:),ja(:) 8090 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8091 ! Access the ith and jth entries via ia(i) and ja(j) 8092 .ve 8093 8094 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8095 @*/ 8096 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8097 { 8098 PetscFunctionBegin; 8099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8100 PetscValidType(mat, 1); 8101 if (n) PetscAssertPointer(n, 5); 8102 if (ia) PetscAssertPointer(ia, 6); 8103 if (ja) PetscAssertPointer(ja, 7); 8104 if (done) PetscAssertPointer(done, 8); 8105 MatCheckPreallocated(mat, 1); 8106 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8107 else { 8108 if (done) *done = PETSC_TRUE; 8109 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8110 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8111 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8112 } 8113 PetscFunctionReturn(PETSC_SUCCESS); 8114 } 8115 8116 /*@C 8117 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8118 8119 Collective 8120 8121 Input Parameters: 8122 + mat - the matrix 8123 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8124 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8125 symmetrized 8126 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8127 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8128 always used. 8129 . n - number of columns in the (possibly compressed) matrix 8130 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8131 - ja - the row indices 8132 8133 Output Parameter: 8134 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8135 8136 Level: developer 8137 8138 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8139 @*/ 8140 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8141 { 8142 PetscFunctionBegin; 8143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8144 PetscValidType(mat, 1); 8145 PetscAssertPointer(n, 5); 8146 if (ia) PetscAssertPointer(ia, 6); 8147 if (ja) PetscAssertPointer(ja, 7); 8148 PetscAssertPointer(done, 8); 8149 MatCheckPreallocated(mat, 1); 8150 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8151 else { 8152 *done = PETSC_TRUE; 8153 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8154 } 8155 PetscFunctionReturn(PETSC_SUCCESS); 8156 } 8157 8158 /*@C 8159 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8160 8161 Collective 8162 8163 Input Parameters: 8164 + mat - the matrix 8165 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8166 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8167 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8168 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8169 always used. 8170 . n - size of (possibly compressed) matrix 8171 . ia - the row pointers 8172 - ja - the column indices 8173 8174 Output Parameter: 8175 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8176 8177 Level: developer 8178 8179 Note: 8180 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8181 us of the array after it has been restored. If you pass `NULL`, it will 8182 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8183 8184 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8185 @*/ 8186 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8187 { 8188 PetscFunctionBegin; 8189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8190 PetscValidType(mat, 1); 8191 if (ia) PetscAssertPointer(ia, 6); 8192 if (ja) PetscAssertPointer(ja, 7); 8193 if (done) PetscAssertPointer(done, 8); 8194 MatCheckPreallocated(mat, 1); 8195 8196 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8197 else { 8198 if (done) *done = PETSC_TRUE; 8199 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8200 if (n) *n = 0; 8201 if (ia) *ia = NULL; 8202 if (ja) *ja = NULL; 8203 } 8204 PetscFunctionReturn(PETSC_SUCCESS); 8205 } 8206 8207 /*@C 8208 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8209 8210 Collective 8211 8212 Input Parameters: 8213 + mat - the matrix 8214 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8215 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8216 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8217 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8218 always used. 8219 8220 Output Parameters: 8221 + n - size of (possibly compressed) matrix 8222 . ia - the column pointers 8223 . ja - the row indices 8224 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8225 8226 Level: developer 8227 8228 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8229 @*/ 8230 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8231 { 8232 PetscFunctionBegin; 8233 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8234 PetscValidType(mat, 1); 8235 if (ia) PetscAssertPointer(ia, 6); 8236 if (ja) PetscAssertPointer(ja, 7); 8237 PetscAssertPointer(done, 8); 8238 MatCheckPreallocated(mat, 1); 8239 8240 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8241 else { 8242 *done = PETSC_TRUE; 8243 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8244 if (n) *n = 0; 8245 if (ia) *ia = NULL; 8246 if (ja) *ja = NULL; 8247 } 8248 PetscFunctionReturn(PETSC_SUCCESS); 8249 } 8250 8251 /*@ 8252 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8253 `MatGetColumnIJ()`. 8254 8255 Collective 8256 8257 Input Parameters: 8258 + mat - the matrix 8259 . ncolors - maximum color value 8260 . n - number of entries in colorarray 8261 - colorarray - array indicating color for each column 8262 8263 Output Parameter: 8264 . iscoloring - coloring generated using colorarray information 8265 8266 Level: developer 8267 8268 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8269 @*/ 8270 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8271 { 8272 PetscFunctionBegin; 8273 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8274 PetscValidType(mat, 1); 8275 PetscAssertPointer(colorarray, 4); 8276 PetscAssertPointer(iscoloring, 5); 8277 MatCheckPreallocated(mat, 1); 8278 8279 if (!mat->ops->coloringpatch) { 8280 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8281 } else { 8282 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8283 } 8284 PetscFunctionReturn(PETSC_SUCCESS); 8285 } 8286 8287 /*@ 8288 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8289 8290 Logically Collective 8291 8292 Input Parameter: 8293 . mat - the factored matrix to be reset 8294 8295 Level: developer 8296 8297 Notes: 8298 This routine should be used only with factored matrices formed by in-place 8299 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8300 format). This option can save memory, for example, when solving nonlinear 8301 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8302 ILU(0) preconditioner. 8303 8304 One can specify in-place ILU(0) factorization by calling 8305 .vb 8306 PCType(pc,PCILU); 8307 PCFactorSeUseInPlace(pc); 8308 .ve 8309 or by using the options -pc_type ilu -pc_factor_in_place 8310 8311 In-place factorization ILU(0) can also be used as a local 8312 solver for the blocks within the block Jacobi or additive Schwarz 8313 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8314 for details on setting local solver options. 8315 8316 Most users should employ the `KSP` interface for linear solvers 8317 instead of working directly with matrix algebra routines such as this. 8318 See, e.g., `KSPCreate()`. 8319 8320 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8321 @*/ 8322 PetscErrorCode MatSetUnfactored(Mat mat) 8323 { 8324 PetscFunctionBegin; 8325 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8326 PetscValidType(mat, 1); 8327 MatCheckPreallocated(mat, 1); 8328 mat->factortype = MAT_FACTOR_NONE; 8329 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8330 PetscUseTypeMethod(mat, setunfactored); 8331 PetscFunctionReturn(PETSC_SUCCESS); 8332 } 8333 8334 /*@ 8335 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8336 as the original matrix. 8337 8338 Collective 8339 8340 Input Parameters: 8341 + mat - the original matrix 8342 . isrow - parallel `IS` containing the rows this processor should obtain 8343 . 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. 8344 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8345 8346 Output Parameter: 8347 . newmat - the new submatrix, of the same type as the original matrix 8348 8349 Level: advanced 8350 8351 Notes: 8352 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8353 8354 Some matrix types place restrictions on the row and column indices, such 8355 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; 8356 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8357 8358 The index sets may not have duplicate entries. 8359 8360 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8361 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8362 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8363 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8364 you are finished using it. 8365 8366 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8367 the input matrix. 8368 8369 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8370 8371 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8372 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8373 8374 Example usage: 8375 Consider the following 8x8 matrix with 34 non-zero values, that is 8376 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8377 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8378 as follows 8379 .vb 8380 1 2 0 | 0 3 0 | 0 4 8381 Proc0 0 5 6 | 7 0 0 | 8 0 8382 9 0 10 | 11 0 0 | 12 0 8383 ------------------------------------- 8384 13 0 14 | 15 16 17 | 0 0 8385 Proc1 0 18 0 | 19 20 21 | 0 0 8386 0 0 0 | 22 23 0 | 24 0 8387 ------------------------------------- 8388 Proc2 25 26 27 | 0 0 28 | 29 0 8389 30 0 0 | 31 32 33 | 0 34 8390 .ve 8391 8392 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8393 8394 .vb 8395 2 0 | 0 3 0 | 0 8396 Proc0 5 6 | 7 0 0 | 8 8397 ------------------------------- 8398 Proc1 18 0 | 19 20 21 | 0 8399 ------------------------------- 8400 Proc2 26 27 | 0 0 28 | 29 8401 0 0 | 31 32 33 | 0 8402 .ve 8403 8404 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8405 @*/ 8406 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8407 { 8408 PetscMPIInt size; 8409 Mat *local; 8410 IS iscoltmp; 8411 PetscBool flg; 8412 8413 PetscFunctionBegin; 8414 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8415 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8416 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8417 PetscAssertPointer(newmat, 5); 8418 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8419 PetscValidType(mat, 1); 8420 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8421 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8422 8423 MatCheckPreallocated(mat, 1); 8424 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8425 8426 if (!iscol || isrow == iscol) { 8427 PetscBool stride; 8428 PetscMPIInt grabentirematrix = 0, grab; 8429 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8430 if (stride) { 8431 PetscInt first, step, n, rstart, rend; 8432 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8433 if (step == 1) { 8434 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8435 if (rstart == first) { 8436 PetscCall(ISGetLocalSize(isrow, &n)); 8437 if (n == rend - rstart) grabentirematrix = 1; 8438 } 8439 } 8440 } 8441 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8442 if (grab) { 8443 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8444 if (cll == MAT_INITIAL_MATRIX) { 8445 *newmat = mat; 8446 PetscCall(PetscObjectReference((PetscObject)mat)); 8447 } 8448 PetscFunctionReturn(PETSC_SUCCESS); 8449 } 8450 } 8451 8452 if (!iscol) { 8453 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8454 } else { 8455 iscoltmp = iscol; 8456 } 8457 8458 /* if original matrix is on just one processor then use submatrix generated */ 8459 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8460 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8461 goto setproperties; 8462 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8463 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8464 *newmat = *local; 8465 PetscCall(PetscFree(local)); 8466 goto setproperties; 8467 } else if (!mat->ops->createsubmatrix) { 8468 /* Create a new matrix type that implements the operation using the full matrix */ 8469 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8470 switch (cll) { 8471 case MAT_INITIAL_MATRIX: 8472 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8473 break; 8474 case MAT_REUSE_MATRIX: 8475 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8476 break; 8477 default: 8478 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8479 } 8480 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8481 goto setproperties; 8482 } 8483 8484 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8485 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8486 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8487 8488 setproperties: 8489 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8490 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8491 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8492 } 8493 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8494 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8495 PetscFunctionReturn(PETSC_SUCCESS); 8496 } 8497 8498 /*@ 8499 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8500 8501 Not Collective 8502 8503 Input Parameters: 8504 + A - the matrix we wish to propagate options from 8505 - B - the matrix we wish to propagate options to 8506 8507 Level: beginner 8508 8509 Note: 8510 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8511 8512 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8513 @*/ 8514 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8515 { 8516 PetscFunctionBegin; 8517 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8518 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8519 B->symmetry_eternal = A->symmetry_eternal; 8520 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8521 B->symmetric = A->symmetric; 8522 B->structurally_symmetric = A->structurally_symmetric; 8523 B->spd = A->spd; 8524 B->hermitian = A->hermitian; 8525 PetscFunctionReturn(PETSC_SUCCESS); 8526 } 8527 8528 /*@ 8529 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8530 used during the assembly process to store values that belong to 8531 other processors. 8532 8533 Not Collective 8534 8535 Input Parameters: 8536 + mat - the matrix 8537 . size - the initial size of the stash. 8538 - bsize - the initial size of the block-stash(if used). 8539 8540 Options Database Keys: 8541 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8542 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8543 8544 Level: intermediate 8545 8546 Notes: 8547 The block-stash is used for values set with `MatSetValuesBlocked()` while 8548 the stash is used for values set with `MatSetValues()` 8549 8550 Run with the option -info and look for output of the form 8551 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8552 to determine the appropriate value, MM, to use for size and 8553 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8554 to determine the value, BMM to use for bsize 8555 8556 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8557 @*/ 8558 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8559 { 8560 PetscFunctionBegin; 8561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8562 PetscValidType(mat, 1); 8563 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8564 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8565 PetscFunctionReturn(PETSC_SUCCESS); 8566 } 8567 8568 /*@ 8569 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8570 the matrix 8571 8572 Neighbor-wise Collective 8573 8574 Input Parameters: 8575 + A - the matrix 8576 . x - the vector to be multiplied by the interpolation operator 8577 - y - the vector to be added to the result 8578 8579 Output Parameter: 8580 . w - the resulting vector 8581 8582 Level: intermediate 8583 8584 Notes: 8585 `w` may be the same vector as `y`. 8586 8587 This allows one to use either the restriction or interpolation (its transpose) 8588 matrix to do the interpolation 8589 8590 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8591 @*/ 8592 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8593 { 8594 PetscInt M, N, Ny; 8595 8596 PetscFunctionBegin; 8597 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8598 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8599 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8600 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8601 PetscCall(MatGetSize(A, &M, &N)); 8602 PetscCall(VecGetSize(y, &Ny)); 8603 if (M == Ny) { 8604 PetscCall(MatMultAdd(A, x, y, w)); 8605 } else { 8606 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8607 } 8608 PetscFunctionReturn(PETSC_SUCCESS); 8609 } 8610 8611 /*@ 8612 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8613 the matrix 8614 8615 Neighbor-wise Collective 8616 8617 Input Parameters: 8618 + A - the matrix 8619 - x - the vector to be interpolated 8620 8621 Output Parameter: 8622 . y - the resulting vector 8623 8624 Level: intermediate 8625 8626 Note: 8627 This allows one to use either the restriction or interpolation (its transpose) 8628 matrix to do the interpolation 8629 8630 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8631 @*/ 8632 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8633 { 8634 PetscInt M, N, Ny; 8635 8636 PetscFunctionBegin; 8637 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8638 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8639 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8640 PetscCall(MatGetSize(A, &M, &N)); 8641 PetscCall(VecGetSize(y, &Ny)); 8642 if (M == Ny) { 8643 PetscCall(MatMult(A, x, y)); 8644 } else { 8645 PetscCall(MatMultTranspose(A, x, y)); 8646 } 8647 PetscFunctionReturn(PETSC_SUCCESS); 8648 } 8649 8650 /*@ 8651 MatRestrict - $y = A*x$ or $A^T*x$ 8652 8653 Neighbor-wise Collective 8654 8655 Input Parameters: 8656 + A - the matrix 8657 - x - the vector to be restricted 8658 8659 Output Parameter: 8660 . y - the resulting vector 8661 8662 Level: intermediate 8663 8664 Note: 8665 This allows one to use either the restriction or interpolation (its transpose) 8666 matrix to do the restriction 8667 8668 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8669 @*/ 8670 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8671 { 8672 PetscInt M, N, Nx; 8673 8674 PetscFunctionBegin; 8675 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8676 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8677 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8678 PetscCall(MatGetSize(A, &M, &N)); 8679 PetscCall(VecGetSize(x, &Nx)); 8680 if (M == Nx) { 8681 PetscCall(MatMultTranspose(A, x, y)); 8682 } else { 8683 PetscCall(MatMult(A, x, y)); 8684 } 8685 PetscFunctionReturn(PETSC_SUCCESS); 8686 } 8687 8688 /*@ 8689 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8690 8691 Neighbor-wise Collective 8692 8693 Input Parameters: 8694 + A - the matrix 8695 . x - the input dense matrix to be multiplied 8696 - w - the input dense matrix to be added to the result 8697 8698 Output Parameter: 8699 . y - the output dense matrix 8700 8701 Level: intermediate 8702 8703 Note: 8704 This allows one to use either the restriction or interpolation (its transpose) 8705 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8706 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8707 8708 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8709 @*/ 8710 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8711 { 8712 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8713 PetscBool trans = PETSC_TRUE; 8714 MatReuse reuse = MAT_INITIAL_MATRIX; 8715 8716 PetscFunctionBegin; 8717 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8718 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8719 PetscValidType(x, 2); 8720 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8721 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8722 PetscCall(MatGetSize(A, &M, &N)); 8723 PetscCall(MatGetSize(x, &Mx, &Nx)); 8724 if (N == Mx) trans = PETSC_FALSE; 8725 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); 8726 Mo = trans ? N : M; 8727 if (*y) { 8728 PetscCall(MatGetSize(*y, &My, &Ny)); 8729 if (Mo == My && Nx == Ny) { 8730 reuse = MAT_REUSE_MATRIX; 8731 } else { 8732 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); 8733 PetscCall(MatDestroy(y)); 8734 } 8735 } 8736 8737 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8738 PetscBool flg; 8739 8740 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8741 if (w) { 8742 PetscInt My, Ny, Mw, Nw; 8743 8744 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8745 PetscCall(MatGetSize(*y, &My, &Ny)); 8746 PetscCall(MatGetSize(w, &Mw, &Nw)); 8747 if (!flg || My != Mw || Ny != Nw) w = NULL; 8748 } 8749 if (!w) { 8750 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8751 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8752 PetscCall(PetscObjectDereference((PetscObject)w)); 8753 } else { 8754 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8755 } 8756 } 8757 if (!trans) { 8758 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8759 } else { 8760 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8761 } 8762 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8763 PetscFunctionReturn(PETSC_SUCCESS); 8764 } 8765 8766 /*@ 8767 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8768 8769 Neighbor-wise Collective 8770 8771 Input Parameters: 8772 + A - the matrix 8773 - x - the input dense matrix 8774 8775 Output Parameter: 8776 . y - the output dense matrix 8777 8778 Level: intermediate 8779 8780 Note: 8781 This allows one to use either the restriction or interpolation (its transpose) 8782 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8783 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8784 8785 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8786 @*/ 8787 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8788 { 8789 PetscFunctionBegin; 8790 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8791 PetscFunctionReturn(PETSC_SUCCESS); 8792 } 8793 8794 /*@ 8795 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8796 8797 Neighbor-wise Collective 8798 8799 Input Parameters: 8800 + A - the matrix 8801 - x - the input dense matrix 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 restriction. `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`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8814 @*/ 8815 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8816 { 8817 PetscFunctionBegin; 8818 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8819 PetscFunctionReturn(PETSC_SUCCESS); 8820 } 8821 8822 /*@ 8823 MatGetNullSpace - retrieves the null space of a matrix. 8824 8825 Logically Collective 8826 8827 Input Parameters: 8828 + mat - the matrix 8829 - nullsp - the null space object 8830 8831 Level: developer 8832 8833 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8834 @*/ 8835 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8836 { 8837 PetscFunctionBegin; 8838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8839 PetscAssertPointer(nullsp, 2); 8840 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8841 PetscFunctionReturn(PETSC_SUCCESS); 8842 } 8843 8844 /*@C 8845 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8846 8847 Logically Collective 8848 8849 Input Parameters: 8850 + n - the number of matrices 8851 - mat - the array of matrices 8852 8853 Output Parameters: 8854 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8855 8856 Level: developer 8857 8858 Note: 8859 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8860 8861 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8862 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8863 @*/ 8864 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8865 { 8866 PetscFunctionBegin; 8867 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8868 PetscAssertPointer(mat, 2); 8869 PetscAssertPointer(nullsp, 3); 8870 8871 PetscCall(PetscCalloc1(3 * n, nullsp)); 8872 for (PetscInt i = 0; i < n; i++) { 8873 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8874 (*nullsp)[i] = mat[i]->nullsp; 8875 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8876 (*nullsp)[n + i] = mat[i]->nearnullsp; 8877 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8878 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8879 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8880 } 8881 PetscFunctionReturn(PETSC_SUCCESS); 8882 } 8883 8884 /*@C 8885 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8886 8887 Logically Collective 8888 8889 Input Parameters: 8890 + n - the number of matrices 8891 . mat - the array of matrices 8892 - nullsp - an array of null spaces 8893 8894 Level: developer 8895 8896 Note: 8897 Call `MatGetNullSpaces()` to create `nullsp` 8898 8899 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8900 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8901 @*/ 8902 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8903 { 8904 PetscFunctionBegin; 8905 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8906 PetscAssertPointer(mat, 2); 8907 PetscAssertPointer(nullsp, 3); 8908 PetscAssertPointer(*nullsp, 3); 8909 8910 for (PetscInt i = 0; i < n; i++) { 8911 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8912 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8913 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8914 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8915 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8916 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8917 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8918 } 8919 PetscCall(PetscFree(*nullsp)); 8920 PetscFunctionReturn(PETSC_SUCCESS); 8921 } 8922 8923 /*@ 8924 MatSetNullSpace - attaches a null space to a matrix. 8925 8926 Logically Collective 8927 8928 Input Parameters: 8929 + mat - the matrix 8930 - nullsp - the null space object 8931 8932 Level: advanced 8933 8934 Notes: 8935 This null space is used by the `KSP` linear solvers to solve singular systems. 8936 8937 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` 8938 8939 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 8940 to zero but the linear system will still be solved in a least squares sense. 8941 8942 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8943 the domain of a matrix A (from $R^n$ to $R^m$ (m rows, n columns) $R^n$ = the direct sum of the null space of A, n(A), + the range of $A^T$, $R(A^T)$. 8944 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 8945 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 8946 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$). 8947 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8948 8949 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8950 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8951 routine also automatically calls `MatSetTransposeNullSpace()`. 8952 8953 The user should call `MatNullSpaceDestroy()`. 8954 8955 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8956 `KSPSetPCSide()` 8957 @*/ 8958 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8959 { 8960 PetscFunctionBegin; 8961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8962 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8963 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8964 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8965 mat->nullsp = nullsp; 8966 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8967 PetscFunctionReturn(PETSC_SUCCESS); 8968 } 8969 8970 /*@ 8971 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8972 8973 Logically Collective 8974 8975 Input Parameters: 8976 + mat - the matrix 8977 - nullsp - the null space object 8978 8979 Level: developer 8980 8981 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8982 @*/ 8983 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8984 { 8985 PetscFunctionBegin; 8986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8987 PetscValidType(mat, 1); 8988 PetscAssertPointer(nullsp, 2); 8989 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8990 PetscFunctionReturn(PETSC_SUCCESS); 8991 } 8992 8993 /*@ 8994 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8995 8996 Logically Collective 8997 8998 Input Parameters: 8999 + mat - the matrix 9000 - nullsp - the null space object 9001 9002 Level: advanced 9003 9004 Notes: 9005 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9006 9007 See `MatSetNullSpace()` 9008 9009 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9010 @*/ 9011 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9012 { 9013 PetscFunctionBegin; 9014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9015 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9016 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9017 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9018 mat->transnullsp = nullsp; 9019 PetscFunctionReturn(PETSC_SUCCESS); 9020 } 9021 9022 /*@ 9023 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9024 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9025 9026 Logically Collective 9027 9028 Input Parameters: 9029 + mat - the matrix 9030 - nullsp - the null space object 9031 9032 Level: advanced 9033 9034 Notes: 9035 Overwrites any previous near null space that may have been attached 9036 9037 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9038 9039 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9040 @*/ 9041 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9042 { 9043 PetscFunctionBegin; 9044 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9045 PetscValidType(mat, 1); 9046 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9047 MatCheckPreallocated(mat, 1); 9048 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9049 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9050 mat->nearnullsp = nullsp; 9051 PetscFunctionReturn(PETSC_SUCCESS); 9052 } 9053 9054 /*@ 9055 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9056 9057 Not Collective 9058 9059 Input Parameter: 9060 . mat - the matrix 9061 9062 Output Parameter: 9063 . nullsp - the null space object, `NULL` if not set 9064 9065 Level: advanced 9066 9067 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9068 @*/ 9069 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9070 { 9071 PetscFunctionBegin; 9072 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9073 PetscValidType(mat, 1); 9074 PetscAssertPointer(nullsp, 2); 9075 MatCheckPreallocated(mat, 1); 9076 *nullsp = mat->nearnullsp; 9077 PetscFunctionReturn(PETSC_SUCCESS); 9078 } 9079 9080 /*@ 9081 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9082 9083 Collective 9084 9085 Input Parameters: 9086 + mat - the matrix 9087 . row - row/column permutation 9088 - info - information on desired factorization process 9089 9090 Level: developer 9091 9092 Notes: 9093 Probably really in-place only when level of fill is zero, otherwise allocates 9094 new space to store factored matrix and deletes previous memory. 9095 9096 Most users should employ the `KSP` interface for linear solvers 9097 instead of working directly with matrix algebra routines such as this. 9098 See, e.g., `KSPCreate()`. 9099 9100 Developer Note: 9101 The Fortran interface is not autogenerated as the 9102 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9103 9104 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9105 @*/ 9106 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9107 { 9108 PetscFunctionBegin; 9109 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9110 PetscValidType(mat, 1); 9111 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9112 PetscAssertPointer(info, 3); 9113 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9114 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9115 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9116 MatCheckPreallocated(mat, 1); 9117 PetscUseTypeMethod(mat, iccfactor, row, info); 9118 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9119 PetscFunctionReturn(PETSC_SUCCESS); 9120 } 9121 9122 /*@ 9123 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9124 ghosted ones. 9125 9126 Not Collective 9127 9128 Input Parameters: 9129 + mat - the matrix 9130 - diag - the diagonal values, including ghost ones 9131 9132 Level: developer 9133 9134 Notes: 9135 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9136 9137 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9138 9139 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9140 @*/ 9141 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9142 { 9143 PetscMPIInt size; 9144 9145 PetscFunctionBegin; 9146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9147 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9148 PetscValidType(mat, 1); 9149 9150 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9151 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9152 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9153 if (size == 1) { 9154 PetscInt n, m; 9155 PetscCall(VecGetSize(diag, &n)); 9156 PetscCall(MatGetSize(mat, NULL, &m)); 9157 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9158 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9159 } else { 9160 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9161 } 9162 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9163 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9164 PetscFunctionReturn(PETSC_SUCCESS); 9165 } 9166 9167 /*@ 9168 MatGetInertia - Gets the inertia from a factored matrix 9169 9170 Collective 9171 9172 Input Parameter: 9173 . mat - the matrix 9174 9175 Output Parameters: 9176 + nneg - number of negative eigenvalues 9177 . nzero - number of zero eigenvalues 9178 - npos - number of positive eigenvalues 9179 9180 Level: advanced 9181 9182 Note: 9183 Matrix must have been factored by `MatCholeskyFactor()` 9184 9185 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9186 @*/ 9187 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9188 { 9189 PetscFunctionBegin; 9190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9191 PetscValidType(mat, 1); 9192 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9193 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9194 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9195 PetscFunctionReturn(PETSC_SUCCESS); 9196 } 9197 9198 /*@C 9199 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9200 9201 Neighbor-wise Collective 9202 9203 Input Parameters: 9204 + mat - the factored matrix obtained with `MatGetFactor()` 9205 - b - the right-hand-side vectors 9206 9207 Output Parameter: 9208 . x - the result vectors 9209 9210 Level: developer 9211 9212 Note: 9213 The vectors `b` and `x` cannot be the same. I.e., one cannot 9214 call `MatSolves`(A,x,x). 9215 9216 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9217 @*/ 9218 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9219 { 9220 PetscFunctionBegin; 9221 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9222 PetscValidType(mat, 1); 9223 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9224 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9225 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9226 9227 MatCheckPreallocated(mat, 1); 9228 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9229 PetscUseTypeMethod(mat, solves, b, x); 9230 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9231 PetscFunctionReturn(PETSC_SUCCESS); 9232 } 9233 9234 /*@ 9235 MatIsSymmetric - Test whether a matrix is symmetric 9236 9237 Collective 9238 9239 Input Parameters: 9240 + A - the matrix to test 9241 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9242 9243 Output Parameter: 9244 . flg - the result 9245 9246 Level: intermediate 9247 9248 Notes: 9249 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9250 9251 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9252 9253 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9254 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9255 9256 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9257 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9258 @*/ 9259 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9260 { 9261 PetscFunctionBegin; 9262 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9263 PetscAssertPointer(flg, 3); 9264 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9265 else { 9266 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9267 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9268 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9269 } 9270 PetscFunctionReturn(PETSC_SUCCESS); 9271 } 9272 9273 /*@ 9274 MatIsHermitian - Test whether a matrix is Hermitian 9275 9276 Collective 9277 9278 Input Parameters: 9279 + A - the matrix to test 9280 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9281 9282 Output Parameter: 9283 . flg - the result 9284 9285 Level: intermediate 9286 9287 Notes: 9288 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9289 9290 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9291 9292 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9293 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9294 9295 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9296 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9297 @*/ 9298 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9299 { 9300 PetscFunctionBegin; 9301 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9302 PetscAssertPointer(flg, 3); 9303 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9304 else { 9305 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9306 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9307 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9308 } 9309 PetscFunctionReturn(PETSC_SUCCESS); 9310 } 9311 9312 /*@ 9313 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9314 9315 Not Collective 9316 9317 Input Parameter: 9318 . A - the matrix to check 9319 9320 Output Parameters: 9321 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9322 - flg - the result (only valid if set is `PETSC_TRUE`) 9323 9324 Level: advanced 9325 9326 Notes: 9327 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9328 if you want it explicitly checked 9329 9330 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9331 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9332 9333 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9334 @*/ 9335 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9336 { 9337 PetscFunctionBegin; 9338 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9339 PetscAssertPointer(set, 2); 9340 PetscAssertPointer(flg, 3); 9341 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9342 *set = PETSC_TRUE; 9343 *flg = PetscBool3ToBool(A->symmetric); 9344 } else { 9345 *set = PETSC_FALSE; 9346 } 9347 PetscFunctionReturn(PETSC_SUCCESS); 9348 } 9349 9350 /*@ 9351 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9352 9353 Not Collective 9354 9355 Input Parameter: 9356 . A - the matrix to check 9357 9358 Output Parameters: 9359 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9360 - flg - the result (only valid if set is `PETSC_TRUE`) 9361 9362 Level: advanced 9363 9364 Notes: 9365 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9366 9367 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9368 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9369 9370 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9371 @*/ 9372 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9373 { 9374 PetscFunctionBegin; 9375 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9376 PetscAssertPointer(set, 2); 9377 PetscAssertPointer(flg, 3); 9378 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9379 *set = PETSC_TRUE; 9380 *flg = PetscBool3ToBool(A->spd); 9381 } else { 9382 *set = PETSC_FALSE; 9383 } 9384 PetscFunctionReturn(PETSC_SUCCESS); 9385 } 9386 9387 /*@ 9388 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9389 9390 Not Collective 9391 9392 Input Parameter: 9393 . A - the matrix to check 9394 9395 Output Parameters: 9396 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9397 - flg - the result (only valid if set is `PETSC_TRUE`) 9398 9399 Level: advanced 9400 9401 Notes: 9402 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9403 if you want it explicitly checked 9404 9405 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9406 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9407 9408 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9409 @*/ 9410 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9411 { 9412 PetscFunctionBegin; 9413 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9414 PetscAssertPointer(set, 2); 9415 PetscAssertPointer(flg, 3); 9416 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9417 *set = PETSC_TRUE; 9418 *flg = PetscBool3ToBool(A->hermitian); 9419 } else { 9420 *set = PETSC_FALSE; 9421 } 9422 PetscFunctionReturn(PETSC_SUCCESS); 9423 } 9424 9425 /*@ 9426 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9427 9428 Collective 9429 9430 Input Parameter: 9431 . A - the matrix to test 9432 9433 Output Parameter: 9434 . flg - the result 9435 9436 Level: intermediate 9437 9438 Notes: 9439 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9440 9441 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 9442 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9443 9444 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9445 @*/ 9446 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9447 { 9448 PetscFunctionBegin; 9449 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9450 PetscAssertPointer(flg, 2); 9451 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9452 *flg = PetscBool3ToBool(A->structurally_symmetric); 9453 } else { 9454 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9455 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9456 } 9457 PetscFunctionReturn(PETSC_SUCCESS); 9458 } 9459 9460 /*@ 9461 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9462 9463 Not Collective 9464 9465 Input Parameter: 9466 . A - the matrix to check 9467 9468 Output Parameters: 9469 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9470 - flg - the result (only valid if set is PETSC_TRUE) 9471 9472 Level: advanced 9473 9474 Notes: 9475 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 9476 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9477 9478 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9479 9480 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9481 @*/ 9482 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9483 { 9484 PetscFunctionBegin; 9485 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9486 PetscAssertPointer(set, 2); 9487 PetscAssertPointer(flg, 3); 9488 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9489 *set = PETSC_TRUE; 9490 *flg = PetscBool3ToBool(A->structurally_symmetric); 9491 } else { 9492 *set = PETSC_FALSE; 9493 } 9494 PetscFunctionReturn(PETSC_SUCCESS); 9495 } 9496 9497 /*@ 9498 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9499 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9500 9501 Not Collective 9502 9503 Input Parameter: 9504 . mat - the matrix 9505 9506 Output Parameters: 9507 + nstash - the size of the stash 9508 . reallocs - the number of additional mallocs incurred. 9509 . bnstash - the size of the block stash 9510 - breallocs - the number of additional mallocs incurred.in the block stash 9511 9512 Level: advanced 9513 9514 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9515 @*/ 9516 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9517 { 9518 PetscFunctionBegin; 9519 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9520 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9521 PetscFunctionReturn(PETSC_SUCCESS); 9522 } 9523 9524 /*@ 9525 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9526 parallel layout, `PetscLayout` for rows and columns 9527 9528 Collective 9529 9530 Input Parameter: 9531 . mat - the matrix 9532 9533 Output Parameters: 9534 + right - (optional) vector that the matrix can be multiplied against 9535 - left - (optional) vector that the matrix vector product can be stored in 9536 9537 Level: advanced 9538 9539 Notes: 9540 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()`. 9541 9542 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9543 9544 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9545 @*/ 9546 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9547 { 9548 PetscFunctionBegin; 9549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9550 PetscValidType(mat, 1); 9551 if (mat->ops->getvecs) { 9552 PetscUseTypeMethod(mat, getvecs, right, left); 9553 } else { 9554 if (right) { 9555 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9556 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9557 PetscCall(VecSetType(*right, mat->defaultvectype)); 9558 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9559 if (mat->boundtocpu && mat->bindingpropagates) { 9560 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9561 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9562 } 9563 #endif 9564 } 9565 if (left) { 9566 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9567 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9568 PetscCall(VecSetType(*left, mat->defaultvectype)); 9569 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9570 if (mat->boundtocpu && mat->bindingpropagates) { 9571 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9572 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9573 } 9574 #endif 9575 } 9576 } 9577 PetscFunctionReturn(PETSC_SUCCESS); 9578 } 9579 9580 /*@ 9581 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9582 with default values. 9583 9584 Not Collective 9585 9586 Input Parameter: 9587 . info - the `MatFactorInfo` data structure 9588 9589 Level: developer 9590 9591 Notes: 9592 The solvers are generally used through the `KSP` and `PC` objects, for example 9593 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9594 9595 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9596 9597 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9598 @*/ 9599 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9600 { 9601 PetscFunctionBegin; 9602 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9603 PetscFunctionReturn(PETSC_SUCCESS); 9604 } 9605 9606 /*@ 9607 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9608 9609 Collective 9610 9611 Input Parameters: 9612 + mat - the factored matrix 9613 - is - the index set defining the Schur indices (0-based) 9614 9615 Level: advanced 9616 9617 Notes: 9618 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9619 9620 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9621 9622 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9623 9624 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9625 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9626 @*/ 9627 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9628 { 9629 PetscErrorCode (*f)(Mat, IS); 9630 9631 PetscFunctionBegin; 9632 PetscValidType(mat, 1); 9633 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9634 PetscValidType(is, 2); 9635 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9636 PetscCheckSameComm(mat, 1, is, 2); 9637 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9638 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9639 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9640 PetscCall(MatDestroy(&mat->schur)); 9641 PetscCall((*f)(mat, is)); 9642 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9643 PetscFunctionReturn(PETSC_SUCCESS); 9644 } 9645 9646 /*@ 9647 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9648 9649 Logically Collective 9650 9651 Input Parameters: 9652 + F - the factored matrix obtained by calling `MatGetFactor()` 9653 . S - location where to return the Schur complement, can be `NULL` 9654 - status - the status of the Schur complement matrix, can be `NULL` 9655 9656 Level: advanced 9657 9658 Notes: 9659 You must call `MatFactorSetSchurIS()` before calling this routine. 9660 9661 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9662 9663 The routine provides a copy of the Schur matrix stored within the solver data structures. 9664 The caller must destroy the object when it is no longer needed. 9665 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9666 9667 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) 9668 9669 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9670 9671 Developer Note: 9672 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9673 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9674 9675 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9676 @*/ 9677 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9678 { 9679 PetscFunctionBegin; 9680 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9681 if (S) PetscAssertPointer(S, 2); 9682 if (status) PetscAssertPointer(status, 3); 9683 if (S) { 9684 PetscErrorCode (*f)(Mat, Mat *); 9685 9686 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9687 if (f) { 9688 PetscCall((*f)(F, S)); 9689 } else { 9690 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9691 } 9692 } 9693 if (status) *status = F->schur_status; 9694 PetscFunctionReturn(PETSC_SUCCESS); 9695 } 9696 9697 /*@ 9698 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9699 9700 Logically Collective 9701 9702 Input Parameters: 9703 + F - the factored matrix obtained by calling `MatGetFactor()` 9704 . S - location where to return the Schur complement, can be `NULL` 9705 - status - the status of the Schur complement matrix, can be `NULL` 9706 9707 Level: advanced 9708 9709 Notes: 9710 You must call `MatFactorSetSchurIS()` before calling this routine. 9711 9712 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9713 9714 The routine returns a the Schur Complement stored within the data structures of the solver. 9715 9716 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9717 9718 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9719 9720 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9721 9722 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9723 9724 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9725 @*/ 9726 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9727 { 9728 PetscFunctionBegin; 9729 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9730 if (S) { 9731 PetscAssertPointer(S, 2); 9732 *S = F->schur; 9733 } 9734 if (status) { 9735 PetscAssertPointer(status, 3); 9736 *status = F->schur_status; 9737 } 9738 PetscFunctionReturn(PETSC_SUCCESS); 9739 } 9740 9741 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9742 { 9743 Mat S = F->schur; 9744 9745 PetscFunctionBegin; 9746 switch (F->schur_status) { 9747 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9748 case MAT_FACTOR_SCHUR_INVERTED: 9749 if (S) { 9750 S->ops->solve = NULL; 9751 S->ops->matsolve = NULL; 9752 S->ops->solvetranspose = NULL; 9753 S->ops->matsolvetranspose = NULL; 9754 S->ops->solveadd = NULL; 9755 S->ops->solvetransposeadd = NULL; 9756 S->factortype = MAT_FACTOR_NONE; 9757 PetscCall(PetscFree(S->solvertype)); 9758 } 9759 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9760 break; 9761 default: 9762 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9763 } 9764 PetscFunctionReturn(PETSC_SUCCESS); 9765 } 9766 9767 /*@ 9768 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9769 9770 Logically Collective 9771 9772 Input Parameters: 9773 + F - the factored matrix obtained by calling `MatGetFactor()` 9774 . S - location where the Schur complement is stored 9775 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9776 9777 Level: advanced 9778 9779 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9780 @*/ 9781 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9782 { 9783 PetscFunctionBegin; 9784 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9785 if (S) { 9786 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9787 *S = NULL; 9788 } 9789 F->schur_status = status; 9790 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9791 PetscFunctionReturn(PETSC_SUCCESS); 9792 } 9793 9794 /*@ 9795 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9796 9797 Logically Collective 9798 9799 Input Parameters: 9800 + F - the factored matrix obtained by calling `MatGetFactor()` 9801 . rhs - location where the right-hand side of the Schur complement system is stored 9802 - sol - location where the solution of the Schur complement system has to be returned 9803 9804 Level: advanced 9805 9806 Notes: 9807 The sizes of the vectors should match the size of the Schur complement 9808 9809 Must be called after `MatFactorSetSchurIS()` 9810 9811 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9812 @*/ 9813 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9814 { 9815 PetscFunctionBegin; 9816 PetscValidType(F, 1); 9817 PetscValidType(rhs, 2); 9818 PetscValidType(sol, 3); 9819 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9820 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9821 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9822 PetscCheckSameComm(F, 1, rhs, 2); 9823 PetscCheckSameComm(F, 1, sol, 3); 9824 PetscCall(MatFactorFactorizeSchurComplement(F)); 9825 switch (F->schur_status) { 9826 case MAT_FACTOR_SCHUR_FACTORED: 9827 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9828 break; 9829 case MAT_FACTOR_SCHUR_INVERTED: 9830 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9831 break; 9832 default: 9833 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9834 } 9835 PetscFunctionReturn(PETSC_SUCCESS); 9836 } 9837 9838 /*@ 9839 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9840 9841 Logically Collective 9842 9843 Input Parameters: 9844 + F - the factored matrix obtained by calling `MatGetFactor()` 9845 . rhs - location where the right-hand side of the Schur complement system is stored 9846 - sol - location where the solution of the Schur complement system has to be returned 9847 9848 Level: advanced 9849 9850 Notes: 9851 The sizes of the vectors should match the size of the Schur complement 9852 9853 Must be called after `MatFactorSetSchurIS()` 9854 9855 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9856 @*/ 9857 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9858 { 9859 PetscFunctionBegin; 9860 PetscValidType(F, 1); 9861 PetscValidType(rhs, 2); 9862 PetscValidType(sol, 3); 9863 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9864 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9865 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9866 PetscCheckSameComm(F, 1, rhs, 2); 9867 PetscCheckSameComm(F, 1, sol, 3); 9868 PetscCall(MatFactorFactorizeSchurComplement(F)); 9869 switch (F->schur_status) { 9870 case MAT_FACTOR_SCHUR_FACTORED: 9871 PetscCall(MatSolve(F->schur, rhs, sol)); 9872 break; 9873 case MAT_FACTOR_SCHUR_INVERTED: 9874 PetscCall(MatMult(F->schur, rhs, sol)); 9875 break; 9876 default: 9877 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9878 } 9879 PetscFunctionReturn(PETSC_SUCCESS); 9880 } 9881 9882 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9883 #if PetscDefined(HAVE_CUDA) 9884 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9885 #endif 9886 9887 /* Schur status updated in the interface */ 9888 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9889 { 9890 Mat S = F->schur; 9891 9892 PetscFunctionBegin; 9893 if (S) { 9894 PetscMPIInt size; 9895 PetscBool isdense, isdensecuda; 9896 9897 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9898 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9899 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9900 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9901 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9902 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9903 if (isdense) { 9904 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9905 } else if (isdensecuda) { 9906 #if defined(PETSC_HAVE_CUDA) 9907 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9908 #endif 9909 } 9910 // HIP?????????????? 9911 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9912 } 9913 PetscFunctionReturn(PETSC_SUCCESS); 9914 } 9915 9916 /*@ 9917 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9918 9919 Logically Collective 9920 9921 Input Parameter: 9922 . F - the factored matrix obtained by calling `MatGetFactor()` 9923 9924 Level: advanced 9925 9926 Notes: 9927 Must be called after `MatFactorSetSchurIS()`. 9928 9929 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9930 9931 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9932 @*/ 9933 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9934 { 9935 PetscFunctionBegin; 9936 PetscValidType(F, 1); 9937 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9938 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9939 PetscCall(MatFactorFactorizeSchurComplement(F)); 9940 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9941 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9942 PetscFunctionReturn(PETSC_SUCCESS); 9943 } 9944 9945 /*@ 9946 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9947 9948 Logically Collective 9949 9950 Input Parameter: 9951 . F - the factored matrix obtained by calling `MatGetFactor()` 9952 9953 Level: advanced 9954 9955 Note: 9956 Must be called after `MatFactorSetSchurIS()` 9957 9958 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9959 @*/ 9960 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9961 { 9962 MatFactorInfo info; 9963 9964 PetscFunctionBegin; 9965 PetscValidType(F, 1); 9966 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9967 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9968 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9969 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9970 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9971 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9972 } else { 9973 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9974 } 9975 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9976 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9977 PetscFunctionReturn(PETSC_SUCCESS); 9978 } 9979 9980 /*@ 9981 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9982 9983 Neighbor-wise Collective 9984 9985 Input Parameters: 9986 + A - the matrix 9987 . P - the projection matrix 9988 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9989 - 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 9990 if the result is a dense matrix this is irrelevant 9991 9992 Output Parameter: 9993 . C - the product matrix 9994 9995 Level: intermediate 9996 9997 Notes: 9998 C will be created and must be destroyed by the user with `MatDestroy()`. 9999 10000 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10001 10002 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10003 10004 Developer Note: 10005 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10006 10007 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10008 @*/ 10009 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10010 { 10011 PetscFunctionBegin; 10012 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10013 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10014 10015 if (scall == MAT_INITIAL_MATRIX) { 10016 PetscCall(MatProductCreate(A, P, NULL, C)); 10017 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10018 PetscCall(MatProductSetAlgorithm(*C, "default")); 10019 PetscCall(MatProductSetFill(*C, fill)); 10020 10021 (*C)->product->api_user = PETSC_TRUE; 10022 PetscCall(MatProductSetFromOptions(*C)); 10023 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); 10024 PetscCall(MatProductSymbolic(*C)); 10025 } else { /* scall == MAT_REUSE_MATRIX */ 10026 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10027 } 10028 10029 PetscCall(MatProductNumeric(*C)); 10030 (*C)->symmetric = A->symmetric; 10031 (*C)->spd = A->spd; 10032 PetscFunctionReturn(PETSC_SUCCESS); 10033 } 10034 10035 /*@ 10036 MatRARt - Creates the matrix product $C = R * A * R^T$ 10037 10038 Neighbor-wise Collective 10039 10040 Input Parameters: 10041 + A - the matrix 10042 . R - the projection matrix 10043 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10044 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10045 if the result is a dense matrix this is irrelevant 10046 10047 Output Parameter: 10048 . C - the product matrix 10049 10050 Level: intermediate 10051 10052 Notes: 10053 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10054 10055 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10056 10057 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10058 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10059 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10060 We recommend using `MatPtAP()` when possible. 10061 10062 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10063 10064 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10065 @*/ 10066 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10067 { 10068 PetscFunctionBegin; 10069 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10070 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10071 10072 if (scall == MAT_INITIAL_MATRIX) { 10073 PetscCall(MatProductCreate(A, R, NULL, C)); 10074 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10075 PetscCall(MatProductSetAlgorithm(*C, "default")); 10076 PetscCall(MatProductSetFill(*C, fill)); 10077 10078 (*C)->product->api_user = PETSC_TRUE; 10079 PetscCall(MatProductSetFromOptions(*C)); 10080 PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name); 10081 PetscCall(MatProductSymbolic(*C)); 10082 } else { /* scall == MAT_REUSE_MATRIX */ 10083 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10084 } 10085 10086 PetscCall(MatProductNumeric(*C)); 10087 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10088 PetscFunctionReturn(PETSC_SUCCESS); 10089 } 10090 10091 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10092 { 10093 PetscBool flg = PETSC_TRUE; 10094 10095 PetscFunctionBegin; 10096 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10097 if (scall == MAT_INITIAL_MATRIX) { 10098 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10099 PetscCall(MatProductCreate(A, B, NULL, C)); 10100 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10101 PetscCall(MatProductSetFill(*C, fill)); 10102 } else { /* scall == MAT_REUSE_MATRIX */ 10103 Mat_Product *product = (*C)->product; 10104 10105 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10106 if (flg && product && product->type != ptype) { 10107 PetscCall(MatProductClear(*C)); 10108 product = NULL; 10109 } 10110 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10111 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10112 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10113 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10114 product = (*C)->product; 10115 product->fill = fill; 10116 product->clear = PETSC_TRUE; 10117 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10118 flg = PETSC_FALSE; 10119 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10120 } 10121 } 10122 if (flg) { 10123 (*C)->product->api_user = PETSC_TRUE; 10124 PetscCall(MatProductSetType(*C, ptype)); 10125 PetscCall(MatProductSetFromOptions(*C)); 10126 PetscCall(MatProductSymbolic(*C)); 10127 } 10128 PetscCall(MatProductNumeric(*C)); 10129 PetscFunctionReturn(PETSC_SUCCESS); 10130 } 10131 10132 /*@ 10133 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10134 10135 Neighbor-wise Collective 10136 10137 Input Parameters: 10138 + A - the left matrix 10139 . B - the right matrix 10140 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10141 - 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 10142 if the result is a dense matrix this is irrelevant 10143 10144 Output Parameter: 10145 . C - the product matrix 10146 10147 Notes: 10148 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10149 10150 `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 10151 call to this function with `MAT_INITIAL_MATRIX`. 10152 10153 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10154 10155 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`, 10156 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10157 10158 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10159 10160 Example of Usage: 10161 .vb 10162 MatProductCreate(A,B,NULL,&C); 10163 MatProductSetType(C,MATPRODUCT_AB); 10164 MatProductSymbolic(C); 10165 MatProductNumeric(C); // compute C=A * B 10166 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10167 MatProductNumeric(C); 10168 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10169 MatProductNumeric(C); 10170 .ve 10171 10172 Level: intermediate 10173 10174 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10175 @*/ 10176 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10177 { 10178 PetscFunctionBegin; 10179 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10180 PetscFunctionReturn(PETSC_SUCCESS); 10181 } 10182 10183 /*@ 10184 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10185 10186 Neighbor-wise Collective 10187 10188 Input Parameters: 10189 + A - the left matrix 10190 . B - the right matrix 10191 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10192 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10193 10194 Output Parameter: 10195 . C - the product matrix 10196 10197 Options Database Key: 10198 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10199 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10200 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10201 10202 Level: intermediate 10203 10204 Notes: 10205 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10206 10207 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10208 10209 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10210 actually needed. 10211 10212 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10213 and for pairs of `MATMPIDENSE` matrices. 10214 10215 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10216 10217 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10218 10219 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10220 @*/ 10221 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10222 { 10223 PetscFunctionBegin; 10224 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10225 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10226 PetscFunctionReturn(PETSC_SUCCESS); 10227 } 10228 10229 /*@ 10230 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10231 10232 Neighbor-wise Collective 10233 10234 Input Parameters: 10235 + A - the left matrix 10236 . B - the right matrix 10237 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10238 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10239 10240 Output Parameter: 10241 . C - the product matrix 10242 10243 Level: intermediate 10244 10245 Notes: 10246 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10247 10248 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10249 10250 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10251 10252 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10253 actually needed. 10254 10255 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10256 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10257 10258 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10259 10260 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10261 @*/ 10262 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10263 { 10264 PetscFunctionBegin; 10265 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10266 PetscFunctionReturn(PETSC_SUCCESS); 10267 } 10268 10269 /*@ 10270 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10271 10272 Neighbor-wise Collective 10273 10274 Input Parameters: 10275 + A - the left matrix 10276 . B - the middle matrix 10277 . C - the right matrix 10278 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10279 - 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 10280 if the result is a dense matrix this is irrelevant 10281 10282 Output Parameter: 10283 . D - the product matrix 10284 10285 Level: intermediate 10286 10287 Notes: 10288 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10289 10290 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10291 10292 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10293 10294 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10295 actually needed. 10296 10297 If you have many matrices with the same non-zero structure to multiply, you 10298 should use `MAT_REUSE_MATRIX` in all calls but the first 10299 10300 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10301 10302 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10303 @*/ 10304 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10305 { 10306 PetscFunctionBegin; 10307 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10308 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10309 10310 if (scall == MAT_INITIAL_MATRIX) { 10311 PetscCall(MatProductCreate(A, B, C, D)); 10312 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10313 PetscCall(MatProductSetAlgorithm(*D, "default")); 10314 PetscCall(MatProductSetFill(*D, fill)); 10315 10316 (*D)->product->api_user = PETSC_TRUE; 10317 PetscCall(MatProductSetFromOptions(*D)); 10318 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, 10319 ((PetscObject)C)->type_name); 10320 PetscCall(MatProductSymbolic(*D)); 10321 } else { /* user may change input matrices when REUSE */ 10322 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10323 } 10324 PetscCall(MatProductNumeric(*D)); 10325 PetscFunctionReturn(PETSC_SUCCESS); 10326 } 10327 10328 /*@ 10329 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10330 10331 Collective 10332 10333 Input Parameters: 10334 + mat - the matrix 10335 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10336 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10337 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10338 10339 Output Parameter: 10340 . matredundant - redundant matrix 10341 10342 Level: advanced 10343 10344 Notes: 10345 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10346 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10347 10348 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10349 calling it. 10350 10351 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10352 10353 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10354 @*/ 10355 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10356 { 10357 MPI_Comm comm; 10358 PetscMPIInt size; 10359 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10360 Mat_Redundant *redund = NULL; 10361 PetscSubcomm psubcomm = NULL; 10362 MPI_Comm subcomm_in = subcomm; 10363 Mat *matseq; 10364 IS isrow, iscol; 10365 PetscBool newsubcomm = PETSC_FALSE; 10366 10367 PetscFunctionBegin; 10368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10369 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10370 PetscAssertPointer(*matredundant, 5); 10371 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10372 } 10373 10374 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10375 if (size == 1 || nsubcomm == 1) { 10376 if (reuse == MAT_INITIAL_MATRIX) { 10377 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10378 } else { 10379 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"); 10380 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10381 } 10382 PetscFunctionReturn(PETSC_SUCCESS); 10383 } 10384 10385 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10386 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10387 MatCheckPreallocated(mat, 1); 10388 10389 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10390 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10391 /* create psubcomm, then get subcomm */ 10392 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10393 PetscCallMPI(MPI_Comm_size(comm, &size)); 10394 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10395 10396 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10397 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10398 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10399 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10400 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10401 newsubcomm = PETSC_TRUE; 10402 PetscCall(PetscSubcommDestroy(&psubcomm)); 10403 } 10404 10405 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10406 if (reuse == MAT_INITIAL_MATRIX) { 10407 mloc_sub = PETSC_DECIDE; 10408 nloc_sub = PETSC_DECIDE; 10409 if (bs < 1) { 10410 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10411 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10412 } else { 10413 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10414 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10415 } 10416 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10417 rstart = rend - mloc_sub; 10418 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10419 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10420 PetscCall(ISSetIdentity(iscol)); 10421 } else { /* reuse == MAT_REUSE_MATRIX */ 10422 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"); 10423 /* retrieve subcomm */ 10424 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10425 redund = (*matredundant)->redundant; 10426 isrow = redund->isrow; 10427 iscol = redund->iscol; 10428 matseq = redund->matseq; 10429 } 10430 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10431 10432 /* get matredundant over subcomm */ 10433 if (reuse == MAT_INITIAL_MATRIX) { 10434 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10435 10436 /* create a supporting struct and attach it to C for reuse */ 10437 PetscCall(PetscNew(&redund)); 10438 (*matredundant)->redundant = redund; 10439 redund->isrow = isrow; 10440 redund->iscol = iscol; 10441 redund->matseq = matseq; 10442 if (newsubcomm) { 10443 redund->subcomm = subcomm; 10444 } else { 10445 redund->subcomm = MPI_COMM_NULL; 10446 } 10447 } else { 10448 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10449 } 10450 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10451 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10452 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10453 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10454 } 10455 #endif 10456 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10457 PetscFunctionReturn(PETSC_SUCCESS); 10458 } 10459 10460 /*@C 10461 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10462 a given `Mat`. Each submatrix can span multiple procs. 10463 10464 Collective 10465 10466 Input Parameters: 10467 + mat - the matrix 10468 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10469 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10470 10471 Output Parameter: 10472 . subMat - parallel sub-matrices each spanning a given `subcomm` 10473 10474 Level: advanced 10475 10476 Notes: 10477 The submatrix partition across processors is dictated by `subComm` a 10478 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10479 is not restricted to be grouped with consecutive original MPI processes. 10480 10481 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10482 map directly to the layout of the original matrix [wrt the local 10483 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10484 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10485 the `subMat`. However the offDiagMat looses some columns - and this is 10486 reconstructed with `MatSetValues()` 10487 10488 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10489 10490 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10491 @*/ 10492 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10493 { 10494 PetscMPIInt commsize, subCommSize; 10495 10496 PetscFunctionBegin; 10497 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10498 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10499 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10500 10501 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"); 10502 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10503 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10504 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10505 PetscFunctionReturn(PETSC_SUCCESS); 10506 } 10507 10508 /*@ 10509 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10510 10511 Not Collective 10512 10513 Input Parameters: 10514 + mat - matrix to extract local submatrix from 10515 . isrow - local row indices for submatrix 10516 - iscol - local column indices for submatrix 10517 10518 Output Parameter: 10519 . submat - the submatrix 10520 10521 Level: intermediate 10522 10523 Notes: 10524 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10525 10526 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10527 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10528 10529 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10530 `MatSetValuesBlockedLocal()` will also be implemented. 10531 10532 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10533 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10534 10535 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10536 @*/ 10537 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10538 { 10539 PetscFunctionBegin; 10540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10541 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10542 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10543 PetscCheckSameComm(isrow, 2, iscol, 3); 10544 PetscAssertPointer(submat, 4); 10545 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10546 10547 if (mat->ops->getlocalsubmatrix) { 10548 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10549 } else { 10550 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10551 } 10552 PetscFunctionReturn(PETSC_SUCCESS); 10553 } 10554 10555 /*@ 10556 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10557 10558 Not Collective 10559 10560 Input Parameters: 10561 + mat - matrix to extract local submatrix from 10562 . isrow - local row indices for submatrix 10563 . iscol - local column indices for submatrix 10564 - submat - the submatrix 10565 10566 Level: intermediate 10567 10568 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10569 @*/ 10570 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10571 { 10572 PetscFunctionBegin; 10573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10574 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10575 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10576 PetscCheckSameComm(isrow, 2, iscol, 3); 10577 PetscAssertPointer(submat, 4); 10578 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10579 10580 if (mat->ops->restorelocalsubmatrix) { 10581 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10582 } else { 10583 PetscCall(MatDestroy(submat)); 10584 } 10585 *submat = NULL; 10586 PetscFunctionReturn(PETSC_SUCCESS); 10587 } 10588 10589 /*@ 10590 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10591 10592 Collective 10593 10594 Input Parameter: 10595 . mat - the matrix 10596 10597 Output Parameter: 10598 . is - if any rows have zero diagonals this contains the list of them 10599 10600 Level: developer 10601 10602 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10603 @*/ 10604 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10605 { 10606 PetscFunctionBegin; 10607 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10608 PetscValidType(mat, 1); 10609 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10610 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10611 10612 if (!mat->ops->findzerodiagonals) { 10613 Vec diag; 10614 const PetscScalar *a; 10615 PetscInt *rows; 10616 PetscInt rStart, rEnd, r, nrow = 0; 10617 10618 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10619 PetscCall(MatGetDiagonal(mat, diag)); 10620 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10621 PetscCall(VecGetArrayRead(diag, &a)); 10622 for (r = 0; r < rEnd - rStart; ++r) 10623 if (a[r] == 0.0) ++nrow; 10624 PetscCall(PetscMalloc1(nrow, &rows)); 10625 nrow = 0; 10626 for (r = 0; r < rEnd - rStart; ++r) 10627 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10628 PetscCall(VecRestoreArrayRead(diag, &a)); 10629 PetscCall(VecDestroy(&diag)); 10630 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10631 } else { 10632 PetscUseTypeMethod(mat, findzerodiagonals, is); 10633 } 10634 PetscFunctionReturn(PETSC_SUCCESS); 10635 } 10636 10637 /*@ 10638 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10639 10640 Collective 10641 10642 Input Parameter: 10643 . mat - the matrix 10644 10645 Output Parameter: 10646 . is - contains the list of rows with off block diagonal entries 10647 10648 Level: developer 10649 10650 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10651 @*/ 10652 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10653 { 10654 PetscFunctionBegin; 10655 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10656 PetscValidType(mat, 1); 10657 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10658 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10659 10660 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10661 PetscFunctionReturn(PETSC_SUCCESS); 10662 } 10663 10664 /*@C 10665 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10666 10667 Collective; No Fortran Support 10668 10669 Input Parameter: 10670 . mat - the matrix 10671 10672 Output Parameter: 10673 . values - the block inverses in column major order (FORTRAN-like) 10674 10675 Level: advanced 10676 10677 Notes: 10678 The size of the blocks is determined by the block size of the matrix. 10679 10680 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10681 10682 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10683 10684 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10685 @*/ 10686 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10687 { 10688 PetscFunctionBegin; 10689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10690 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10691 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10692 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10693 PetscFunctionReturn(PETSC_SUCCESS); 10694 } 10695 10696 /*@ 10697 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10698 10699 Collective; No Fortran Support 10700 10701 Input Parameters: 10702 + mat - the matrix 10703 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10704 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10705 10706 Output Parameter: 10707 . values - the block inverses in column major order (FORTRAN-like) 10708 10709 Level: advanced 10710 10711 Notes: 10712 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10713 10714 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10715 10716 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10717 @*/ 10718 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10719 { 10720 PetscFunctionBegin; 10721 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10722 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10723 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10724 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10725 PetscFunctionReturn(PETSC_SUCCESS); 10726 } 10727 10728 /*@ 10729 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10730 10731 Collective 10732 10733 Input Parameters: 10734 + A - the matrix 10735 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10736 10737 Level: advanced 10738 10739 Note: 10740 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10741 10742 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10743 @*/ 10744 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10745 { 10746 const PetscScalar *vals; 10747 PetscInt *dnnz; 10748 PetscInt m, rstart, rend, bs, i, j; 10749 10750 PetscFunctionBegin; 10751 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10752 PetscCall(MatGetBlockSize(A, &bs)); 10753 PetscCall(MatGetLocalSize(A, &m, NULL)); 10754 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10755 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10756 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10757 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10758 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10759 PetscCall(PetscFree(dnnz)); 10760 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10761 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10762 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10763 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10764 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10765 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10766 PetscFunctionReturn(PETSC_SUCCESS); 10767 } 10768 10769 /*@ 10770 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10771 via `MatTransposeColoringCreate()`. 10772 10773 Collective 10774 10775 Input Parameter: 10776 . c - coloring context 10777 10778 Level: intermediate 10779 10780 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10781 @*/ 10782 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10783 { 10784 MatTransposeColoring matcolor = *c; 10785 10786 PetscFunctionBegin; 10787 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10788 if (--((PetscObject)matcolor)->refct > 0) { 10789 matcolor = NULL; 10790 PetscFunctionReturn(PETSC_SUCCESS); 10791 } 10792 10793 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10794 PetscCall(PetscFree(matcolor->rows)); 10795 PetscCall(PetscFree(matcolor->den2sp)); 10796 PetscCall(PetscFree(matcolor->colorforcol)); 10797 PetscCall(PetscFree(matcolor->columns)); 10798 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10799 PetscCall(PetscHeaderDestroy(c)); 10800 PetscFunctionReturn(PETSC_SUCCESS); 10801 } 10802 10803 /*@ 10804 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10805 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10806 `MatTransposeColoring` to sparse `B`. 10807 10808 Collective 10809 10810 Input Parameters: 10811 + coloring - coloring context created with `MatTransposeColoringCreate()` 10812 - B - sparse matrix 10813 10814 Output Parameter: 10815 . Btdense - dense matrix $B^T$ 10816 10817 Level: developer 10818 10819 Note: 10820 These are used internally for some implementations of `MatRARt()` 10821 10822 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10823 @*/ 10824 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10825 { 10826 PetscFunctionBegin; 10827 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10828 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10829 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10830 10831 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10832 PetscFunctionReturn(PETSC_SUCCESS); 10833 } 10834 10835 /*@ 10836 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10837 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10838 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10839 $C_{sp}$ from $C_{den}$. 10840 10841 Collective 10842 10843 Input Parameters: 10844 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10845 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10846 10847 Output Parameter: 10848 . Csp - sparse matrix 10849 10850 Level: developer 10851 10852 Note: 10853 These are used internally for some implementations of `MatRARt()` 10854 10855 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10856 @*/ 10857 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10858 { 10859 PetscFunctionBegin; 10860 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10861 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10862 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10863 10864 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10865 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10866 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10867 PetscFunctionReturn(PETSC_SUCCESS); 10868 } 10869 10870 /*@ 10871 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10872 10873 Collective 10874 10875 Input Parameters: 10876 + mat - the matrix product C 10877 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10878 10879 Output Parameter: 10880 . color - the new coloring context 10881 10882 Level: intermediate 10883 10884 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10885 `MatTransColoringApplyDenToSp()` 10886 @*/ 10887 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10888 { 10889 MatTransposeColoring c; 10890 MPI_Comm comm; 10891 10892 PetscFunctionBegin; 10893 PetscAssertPointer(color, 3); 10894 10895 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10896 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10897 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10898 c->ctype = iscoloring->ctype; 10899 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10900 *color = c; 10901 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10902 PetscFunctionReturn(PETSC_SUCCESS); 10903 } 10904 10905 /*@ 10906 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10907 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10908 10909 Not Collective 10910 10911 Input Parameter: 10912 . mat - the matrix 10913 10914 Output Parameter: 10915 . state - the current state 10916 10917 Level: intermediate 10918 10919 Notes: 10920 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10921 different matrices 10922 10923 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10924 10925 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10926 10927 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10928 @*/ 10929 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10930 { 10931 PetscFunctionBegin; 10932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10933 *state = mat->nonzerostate; 10934 PetscFunctionReturn(PETSC_SUCCESS); 10935 } 10936 10937 /*@ 10938 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10939 matrices from each processor 10940 10941 Collective 10942 10943 Input Parameters: 10944 + comm - the communicators the parallel matrix will live on 10945 . seqmat - the input sequential matrices 10946 . n - number of local columns (or `PETSC_DECIDE`) 10947 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10948 10949 Output Parameter: 10950 . mpimat - the parallel matrix generated 10951 10952 Level: developer 10953 10954 Note: 10955 The number of columns of the matrix in EACH processor MUST be the same. 10956 10957 .seealso: [](ch_matrices), `Mat` 10958 @*/ 10959 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10960 { 10961 PetscMPIInt size; 10962 10963 PetscFunctionBegin; 10964 PetscCallMPI(MPI_Comm_size(comm, &size)); 10965 if (size == 1) { 10966 if (reuse == MAT_INITIAL_MATRIX) { 10967 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10968 } else { 10969 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10970 } 10971 PetscFunctionReturn(PETSC_SUCCESS); 10972 } 10973 10974 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"); 10975 10976 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10977 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10978 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10979 PetscFunctionReturn(PETSC_SUCCESS); 10980 } 10981 10982 /*@ 10983 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10984 10985 Collective 10986 10987 Input Parameters: 10988 + A - the matrix to create subdomains from 10989 - N - requested number of subdomains 10990 10991 Output Parameters: 10992 + n - number of subdomains resulting on this MPI process 10993 - iss - `IS` list with indices of subdomains on this MPI process 10994 10995 Level: advanced 10996 10997 Note: 10998 The number of subdomains must be smaller than the communicator size 10999 11000 .seealso: [](ch_matrices), `Mat`, `IS` 11001 @*/ 11002 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11003 { 11004 MPI_Comm comm, subcomm; 11005 PetscMPIInt size, rank, color; 11006 PetscInt rstart, rend, k; 11007 11008 PetscFunctionBegin; 11009 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11010 PetscCallMPI(MPI_Comm_size(comm, &size)); 11011 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11012 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); 11013 *n = 1; 11014 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11015 color = rank / k; 11016 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11017 PetscCall(PetscMalloc1(1, iss)); 11018 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11019 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11020 PetscCallMPI(MPI_Comm_free(&subcomm)); 11021 PetscFunctionReturn(PETSC_SUCCESS); 11022 } 11023 11024 /*@ 11025 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11026 11027 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11028 If they are not the same, uses `MatMatMatMult()`. 11029 11030 Once the coarse grid problem is constructed, correct for interpolation operators 11031 that are not of full rank, which can legitimately happen in the case of non-nested 11032 geometric multigrid. 11033 11034 Input Parameters: 11035 + restrct - restriction operator 11036 . dA - fine grid matrix 11037 . interpolate - interpolation operator 11038 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11039 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11040 11041 Output Parameter: 11042 . A - the Galerkin coarse matrix 11043 11044 Options Database Key: 11045 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11046 11047 Level: developer 11048 11049 Note: 11050 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11051 11052 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11053 @*/ 11054 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11055 { 11056 IS zerorows; 11057 Vec diag; 11058 11059 PetscFunctionBegin; 11060 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11061 /* Construct the coarse grid matrix */ 11062 if (interpolate == restrct) { 11063 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11064 } else { 11065 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11066 } 11067 11068 /* If the interpolation matrix is not of full rank, A will have zero rows. 11069 This can legitimately happen in the case of non-nested geometric multigrid. 11070 In that event, we set the rows of the matrix to the rows of the identity, 11071 ignoring the equations (as the RHS will also be zero). */ 11072 11073 PetscCall(MatFindZeroRows(*A, &zerorows)); 11074 11075 if (zerorows != NULL) { /* if there are any zero rows */ 11076 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11077 PetscCall(MatGetDiagonal(*A, diag)); 11078 PetscCall(VecISSet(diag, zerorows, 1.0)); 11079 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11080 PetscCall(VecDestroy(&diag)); 11081 PetscCall(ISDestroy(&zerorows)); 11082 } 11083 PetscFunctionReturn(PETSC_SUCCESS); 11084 } 11085 11086 /*@C 11087 MatSetOperation - Allows user to set a matrix operation for any matrix type 11088 11089 Logically Collective 11090 11091 Input Parameters: 11092 + mat - the matrix 11093 . op - the name of the operation 11094 - f - the function that provides the operation 11095 11096 Level: developer 11097 11098 Example Usage: 11099 .vb 11100 extern PetscErrorCode usermult(Mat, Vec, Vec); 11101 11102 PetscCall(MatCreateXXX(comm, ..., &A)); 11103 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11104 .ve 11105 11106 Notes: 11107 See the file `include/petscmat.h` for a complete list of matrix 11108 operations, which all have the form MATOP_<OPERATION>, where 11109 <OPERATION> is the name (in all capital letters) of the 11110 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11111 11112 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11113 sequence as the usual matrix interface routines, since they 11114 are intended to be accessed via the usual matrix interface 11115 routines, e.g., 11116 .vb 11117 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11118 .ve 11119 11120 In particular each function MUST return `PETSC_SUCCESS` on success and 11121 nonzero on failure. 11122 11123 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11124 11125 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11126 @*/ 11127 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11128 { 11129 PetscFunctionBegin; 11130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11131 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11132 (((void (**)(void))mat->ops)[op]) = f; 11133 PetscFunctionReturn(PETSC_SUCCESS); 11134 } 11135 11136 /*@C 11137 MatGetOperation - Gets a matrix operation for any matrix type. 11138 11139 Not Collective 11140 11141 Input Parameters: 11142 + mat - the matrix 11143 - op - the name of the operation 11144 11145 Output Parameter: 11146 . f - the function that provides the operation 11147 11148 Level: developer 11149 11150 Example Usage: 11151 .vb 11152 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11153 11154 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11155 .ve 11156 11157 Notes: 11158 See the file include/petscmat.h for a complete list of matrix 11159 operations, which all have the form MATOP_<OPERATION>, where 11160 <OPERATION> is the name (in all capital letters) of the 11161 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11162 11163 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11164 11165 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11166 @*/ 11167 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11168 { 11169 PetscFunctionBegin; 11170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11171 *f = (((void (**)(void))mat->ops)[op]); 11172 PetscFunctionReturn(PETSC_SUCCESS); 11173 } 11174 11175 /*@ 11176 MatHasOperation - Determines whether the given matrix supports the particular operation. 11177 11178 Not Collective 11179 11180 Input Parameters: 11181 + mat - the matrix 11182 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11183 11184 Output Parameter: 11185 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11186 11187 Level: advanced 11188 11189 Note: 11190 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11191 11192 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11193 @*/ 11194 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11195 { 11196 PetscFunctionBegin; 11197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11198 PetscAssertPointer(has, 3); 11199 if (mat->ops->hasoperation) { 11200 PetscUseTypeMethod(mat, hasoperation, op, has); 11201 } else { 11202 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11203 else { 11204 *has = PETSC_FALSE; 11205 if (op == MATOP_CREATE_SUBMATRIX) { 11206 PetscMPIInt size; 11207 11208 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11209 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11210 } 11211 } 11212 } 11213 PetscFunctionReturn(PETSC_SUCCESS); 11214 } 11215 11216 /*@ 11217 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11218 11219 Collective 11220 11221 Input Parameter: 11222 . mat - the matrix 11223 11224 Output Parameter: 11225 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11226 11227 Level: beginner 11228 11229 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11230 @*/ 11231 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11232 { 11233 PetscFunctionBegin; 11234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11235 PetscValidType(mat, 1); 11236 PetscAssertPointer(cong, 2); 11237 if (!mat->rmap || !mat->cmap) { 11238 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11239 PetscFunctionReturn(PETSC_SUCCESS); 11240 } 11241 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11242 PetscCall(PetscLayoutSetUp(mat->rmap)); 11243 PetscCall(PetscLayoutSetUp(mat->cmap)); 11244 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11245 if (*cong) mat->congruentlayouts = 1; 11246 else mat->congruentlayouts = 0; 11247 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11248 PetscFunctionReturn(PETSC_SUCCESS); 11249 } 11250 11251 PetscErrorCode MatSetInf(Mat A) 11252 { 11253 PetscFunctionBegin; 11254 PetscUseTypeMethod(A, setinf); 11255 PetscFunctionReturn(PETSC_SUCCESS); 11256 } 11257 11258 /*@ 11259 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 11260 and possibly removes small values from the graph structure. 11261 11262 Collective 11263 11264 Input Parameters: 11265 + A - the matrix 11266 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11267 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11268 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11269 . num_idx - size of 'index' array 11270 - index - array of block indices to use for graph strength of connection weight 11271 11272 Output Parameter: 11273 . graph - the resulting graph 11274 11275 Level: advanced 11276 11277 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11278 @*/ 11279 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11280 { 11281 PetscFunctionBegin; 11282 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11283 PetscValidType(A, 1); 11284 PetscValidLogicalCollectiveBool(A, scale, 3); 11285 PetscAssertPointer(graph, 7); 11286 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11287 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11288 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11289 PetscFunctionReturn(PETSC_SUCCESS); 11290 } 11291 11292 /*@ 11293 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11294 meaning the same memory is used for the matrix, and no new memory is allocated. 11295 11296 Collective 11297 11298 Input Parameters: 11299 + A - the matrix 11300 - 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 11301 11302 Level: intermediate 11303 11304 Developer Note: 11305 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11306 of the arrays in the data structure are unneeded. 11307 11308 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11309 @*/ 11310 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11311 { 11312 PetscFunctionBegin; 11313 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11314 PetscUseTypeMethod(A, eliminatezeros, keep); 11315 PetscFunctionReturn(PETSC_SUCCESS); 11316 } 11317