1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscTryMethod(A, "MatSetOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 759 PetscFunctionReturn(PETSC_SUCCESS); 760 } 761 762 /*@ 763 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 764 for matrices created with `MatGetFactor()` 765 766 Logically Collective 767 768 Input Parameters: 769 + A - the matrix 770 - prefix - the prefix to prepend to all option names for the factored matrix 771 772 Level: developer 773 774 Notes: 775 A hyphen (-) must NOT be given at the beginning of the prefix name. 776 The first character of all runtime options is AUTOMATICALLY the hyphen. 777 778 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 779 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 780 781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 782 @*/ 783 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 784 { 785 PetscFunctionBegin; 786 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 787 if (prefix) { 788 PetscAssertPointer(prefix, 2); 789 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 790 if (prefix != A->factorprefix) { 791 PetscCall(PetscFree(A->factorprefix)); 792 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 793 } 794 } else PetscCall(PetscFree(A->factorprefix)); 795 PetscFunctionReturn(PETSC_SUCCESS); 796 } 797 798 /*@ 799 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 800 for matrices created with `MatGetFactor()` 801 802 Logically Collective 803 804 Input Parameters: 805 + A - the matrix 806 - prefix - the prefix to prepend to all option names for the factored matrix 807 808 Level: developer 809 810 Notes: 811 A hyphen (-) must NOT be given at the beginning of the prefix name. 812 The first character of all runtime options is AUTOMATICALLY the hyphen. 813 814 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 815 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 816 817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 818 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 819 `MatSetOptionsPrefix()` 820 @*/ 821 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 822 { 823 size_t len1, len2, new_len; 824 825 PetscFunctionBegin; 826 PetscValidHeader(A, 1); 827 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 828 if (!A->factorprefix) { 829 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 830 PetscFunctionReturn(PETSC_SUCCESS); 831 } 832 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 833 834 PetscCall(PetscStrlen(A->factorprefix, &len1)); 835 PetscCall(PetscStrlen(prefix, &len2)); 836 new_len = len1 + len2 + 1; 837 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 838 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 839 PetscFunctionReturn(PETSC_SUCCESS); 840 } 841 842 /*@ 843 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 844 matrix options in the database. 845 846 Logically Collective 847 848 Input Parameters: 849 + A - the matrix 850 - prefix - the prefix to prepend to all option names 851 852 Level: advanced 853 854 Note: 855 A hyphen (-) must NOT be given at the beginning of the prefix name. 856 The first character of all runtime options is AUTOMATICALLY the hyphen. 857 858 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 859 @*/ 860 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 861 { 862 PetscFunctionBegin; 863 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 864 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 865 PetscTryMethod(A, "MatAppendOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 866 PetscFunctionReturn(PETSC_SUCCESS); 867 } 868 869 /*@ 870 MatGetOptionsPrefix - Gets the prefix used for searching for all 871 matrix options in the database. 872 873 Not Collective 874 875 Input Parameter: 876 . A - the matrix 877 878 Output Parameter: 879 . prefix - pointer to the prefix string used 880 881 Level: advanced 882 883 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 884 @*/ 885 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 886 { 887 PetscFunctionBegin; 888 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 889 PetscAssertPointer(prefix, 2); 890 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 891 PetscFunctionReturn(PETSC_SUCCESS); 892 } 893 894 /*@ 895 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 896 897 Not Collective 898 899 Input Parameter: 900 . A - the matrix 901 902 Output Parameter: 903 . state - the object state 904 905 Level: advanced 906 907 Note: 908 Object state is an integer which gets increased every time 909 the object is changed. By saving and later querying the object state 910 one can determine whether information about the object is still current. 911 912 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 913 914 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 915 @*/ 916 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 917 { 918 PetscFunctionBegin; 919 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 920 PetscAssertPointer(state, 2); 921 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 922 PetscFunctionReturn(PETSC_SUCCESS); 923 } 924 925 /*@ 926 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 927 928 Collective 929 930 Input Parameter: 931 . A - the matrix 932 933 Level: beginner 934 935 Notes: 936 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 937 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 938 makes all of the preallocation space available 939 940 Current values in the matrix are lost in this call 941 942 Currently only supported for `MATAIJ` matrices. 943 944 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 945 @*/ 946 PetscErrorCode MatResetPreallocation(Mat A) 947 { 948 PetscFunctionBegin; 949 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 950 PetscValidType(A, 1); 951 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 952 PetscFunctionReturn(PETSC_SUCCESS); 953 } 954 955 /*@ 956 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 957 958 Collective 959 960 Input Parameter: 961 . A - the matrix 962 963 Level: intermediate 964 965 Notes: 966 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 967 968 Currently only supported for `MATAIJ` matrices. 969 970 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 971 @*/ 972 PetscErrorCode MatResetHash(Mat A) 973 { 974 PetscFunctionBegin; 975 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 976 PetscValidType(A, 1); 977 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 978 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 979 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 980 /* These flags are used to determine whether certain setups occur */ 981 A->was_assembled = PETSC_FALSE; 982 A->assembled = PETSC_FALSE; 983 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 984 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 985 PetscFunctionReturn(PETSC_SUCCESS); 986 } 987 988 /*@ 989 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 990 991 Collective 992 993 Input Parameter: 994 . A - the matrix 995 996 Level: advanced 997 998 Notes: 999 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1000 setting values in the matrix. 1001 1002 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1003 1004 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1005 @*/ 1006 PetscErrorCode MatSetUp(Mat A) 1007 { 1008 PetscFunctionBegin; 1009 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1010 if (!((PetscObject)A)->type_name) { 1011 PetscMPIInt size; 1012 1013 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1014 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1015 } 1016 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1017 PetscCall(PetscLayoutSetUp(A->rmap)); 1018 PetscCall(PetscLayoutSetUp(A->cmap)); 1019 A->preallocated = PETSC_TRUE; 1020 PetscFunctionReturn(PETSC_SUCCESS); 1021 } 1022 1023 #if defined(PETSC_HAVE_SAWS) 1024 #include <petscviewersaws.h> 1025 #endif 1026 1027 /* 1028 If threadsafety is on extraneous matrices may be printed 1029 1030 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1031 */ 1032 #if !defined(PETSC_HAVE_THREADSAFETY) 1033 static PetscInt insidematview = 0; 1034 #endif 1035 1036 /*@ 1037 MatViewFromOptions - View properties of the matrix based on options set in the options database 1038 1039 Collective 1040 1041 Input Parameters: 1042 + A - the matrix 1043 . obj - optional additional object that provides the options prefix to use 1044 - name - command line option 1045 1046 Options Database Key: 1047 . -mat_view [viewertype]:... - the viewer and its options 1048 1049 Level: intermediate 1050 1051 Note: 1052 .vb 1053 If no value is provided ascii:stdout is used 1054 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1055 for example ascii::ascii_info prints just the information about the object not all details 1056 unless :append is given filename opens in write mode, overwriting what was already there 1057 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1058 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1059 socket[:port] defaults to the standard output port 1060 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1061 .ve 1062 1063 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1064 @*/ 1065 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1066 { 1067 PetscFunctionBegin; 1068 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1069 #if !defined(PETSC_HAVE_THREADSAFETY) 1070 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1071 #endif 1072 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1073 PetscFunctionReturn(PETSC_SUCCESS); 1074 } 1075 1076 /*@ 1077 MatView - display information about a matrix in a variety ways 1078 1079 Collective on viewer 1080 1081 Input Parameters: 1082 + mat - the matrix 1083 - viewer - visualization context 1084 1085 Options Database Keys: 1086 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1087 . -mat_view ::ascii_info_detail - Prints more detailed info 1088 . -mat_view - Prints matrix in ASCII format 1089 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1090 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1091 . -display <name> - Sets display name (default is host) 1092 . -draw_pause <sec> - Sets number of seconds to pause after display 1093 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1094 . -viewer_socket_machine <machine> - - 1095 . -viewer_socket_port <port> - - 1096 . -mat_view binary - save matrix to file in binary format 1097 - -viewer_binary_filename <name> - - 1098 1099 Level: beginner 1100 1101 Notes: 1102 The available visualization contexts include 1103 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1104 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1105 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1106 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1107 1108 The user can open alternative visualization contexts with 1109 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1110 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1111 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1112 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1113 1114 The user can call `PetscViewerPushFormat()` to specify the output 1115 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1116 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1117 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1118 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1119 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1120 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1121 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1122 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1123 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1124 1125 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1126 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1127 1128 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1129 1130 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1131 viewer is used. 1132 1133 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1134 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1135 1136 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1137 and then use the following mouse functions. 1138 .vb 1139 left mouse: zoom in 1140 middle mouse: zoom out 1141 right mouse: continue with the simulation 1142 .ve 1143 1144 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1145 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1146 @*/ 1147 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1148 { 1149 PetscInt rows, cols, rbs, cbs; 1150 PetscBool isascii, isstring, issaws; 1151 PetscViewerFormat format; 1152 PetscMPIInt size; 1153 1154 PetscFunctionBegin; 1155 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1156 PetscValidType(mat, 1); 1157 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1158 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1159 1160 PetscCall(PetscViewerGetFormat(viewer, &format)); 1161 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1162 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1163 1164 #if !defined(PETSC_HAVE_THREADSAFETY) 1165 insidematview++; 1166 #endif 1167 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1168 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1169 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1170 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1171 1172 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1173 if (isascii) { 1174 if (!mat->preallocated) { 1175 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1176 #if !defined(PETSC_HAVE_THREADSAFETY) 1177 insidematview--; 1178 #endif 1179 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1180 PetscFunctionReturn(PETSC_SUCCESS); 1181 } 1182 if (!mat->assembled) { 1183 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1184 #if !defined(PETSC_HAVE_THREADSAFETY) 1185 insidematview--; 1186 #endif 1187 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1188 PetscFunctionReturn(PETSC_SUCCESS); 1189 } 1190 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1191 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1192 MatNullSpace nullsp, transnullsp; 1193 1194 PetscCall(PetscViewerASCIIPushTab(viewer)); 1195 PetscCall(MatGetSize(mat, &rows, &cols)); 1196 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1197 if (rbs != 1 || cbs != 1) { 1198 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : "")); 1199 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1200 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1201 if (mat->factortype) { 1202 MatSolverType solver; 1203 PetscCall(MatFactorGetSolverType(mat, &solver)); 1204 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1205 } 1206 if (mat->ops->getinfo) { 1207 PetscBool is_constant_or_diagonal; 1208 1209 // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output 1210 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, "")); 1211 if (!is_constant_or_diagonal) { 1212 MatInfo info; 1213 1214 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1215 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1216 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1217 } 1218 } 1219 PetscCall(MatGetNullSpace(mat, &nullsp)); 1220 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1221 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1222 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1223 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1224 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1225 PetscCall(PetscViewerASCIIPushTab(viewer)); 1226 PetscCall(MatProductView(mat, viewer)); 1227 PetscCall(PetscViewerASCIIPopTab(viewer)); 1228 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1229 IS tmp; 1230 1231 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1232 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1233 PetscCall(PetscViewerASCIIPushTab(viewer)); 1234 PetscCall(ISView(tmp, viewer)); 1235 PetscCall(PetscViewerASCIIPopTab(viewer)); 1236 PetscCall(ISDestroy(&tmp)); 1237 } 1238 } 1239 } else if (issaws) { 1240 #if defined(PETSC_HAVE_SAWS) 1241 PetscMPIInt rank; 1242 1243 PetscCall(PetscObjectName((PetscObject)mat)); 1244 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1245 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1246 #endif 1247 } else if (isstring) { 1248 const char *type; 1249 PetscCall(MatGetType(mat, &type)); 1250 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1251 PetscTryTypeMethod(mat, view, viewer); 1252 } 1253 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1254 PetscCall(PetscViewerASCIIPushTab(viewer)); 1255 PetscUseTypeMethod(mat, viewnative, viewer); 1256 PetscCall(PetscViewerASCIIPopTab(viewer)); 1257 } else if (mat->ops->view) { 1258 PetscCall(PetscViewerASCIIPushTab(viewer)); 1259 PetscUseTypeMethod(mat, view, viewer); 1260 PetscCall(PetscViewerASCIIPopTab(viewer)); 1261 } 1262 if (isascii) { 1263 PetscCall(PetscViewerGetFormat(viewer, &format)); 1264 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1265 } 1266 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1267 #if !defined(PETSC_HAVE_THREADSAFETY) 1268 insidematview--; 1269 #endif 1270 PetscFunctionReturn(PETSC_SUCCESS); 1271 } 1272 1273 #if defined(PETSC_USE_DEBUG) 1274 #include <../src/sys/totalview/tv_data_display.h> 1275 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1276 { 1277 TV_add_row("Local rows", "int", &mat->rmap->n); 1278 TV_add_row("Local columns", "int", &mat->cmap->n); 1279 TV_add_row("Global rows", "int", &mat->rmap->N); 1280 TV_add_row("Global columns", "int", &mat->cmap->N); 1281 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1282 return TV_format_OK; 1283 } 1284 #endif 1285 1286 /*@ 1287 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1288 with `MatView()`. The matrix format is determined from the options database. 1289 Generates a parallel MPI matrix if the communicator has more than one 1290 processor. The default matrix type is `MATAIJ`. 1291 1292 Collective 1293 1294 Input Parameters: 1295 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1296 or some related function before a call to `MatLoad()` 1297 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1298 1299 Options Database Key: 1300 . -matload_block_size <bs> - set block size 1301 1302 Level: beginner 1303 1304 Notes: 1305 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1306 `Mat` before calling this routine if you wish to set it from the options database. 1307 1308 `MatLoad()` automatically loads into the options database any options 1309 given in the file filename.info where filename is the name of the file 1310 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1311 file will be ignored if you use the -viewer_binary_skip_info option. 1312 1313 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1314 sets the default matrix type AIJ and sets the local and global sizes. 1315 If type and/or size is already set, then the same are used. 1316 1317 In parallel, each processor can load a subset of rows (or the 1318 entire matrix). This routine is especially useful when a large 1319 matrix is stored on disk and only part of it is desired on each 1320 processor. For example, a parallel solver may access only some of 1321 the rows from each processor. The algorithm used here reads 1322 relatively small blocks of data rather than reading the entire 1323 matrix and then subsetting it. 1324 1325 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1326 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1327 or the sequence like 1328 .vb 1329 `PetscViewer` v; 1330 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1331 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1332 `PetscViewerSetFromOptions`(v); 1333 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1334 `PetscViewerFileSetName`(v,"datafile"); 1335 .ve 1336 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1337 .vb 1338 -viewer_type {binary, hdf5} 1339 .ve 1340 1341 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1342 and src/mat/tutorials/ex10.c with the second approach. 1343 1344 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1345 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1346 Multiple objects, both matrices and vectors, can be stored within the same file. 1347 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1348 1349 Most users should not need to know the details of the binary storage 1350 format, since `MatLoad()` and `MatView()` completely hide these details. 1351 But for anyone who is interested, the standard binary matrix storage 1352 format is 1353 1354 .vb 1355 PetscInt MAT_FILE_CLASSID 1356 PetscInt number of rows 1357 PetscInt number of columns 1358 PetscInt total number of nonzeros 1359 PetscInt *number nonzeros in each row 1360 PetscInt *column indices of all nonzeros (starting index is zero) 1361 PetscScalar *values of all nonzeros 1362 .ve 1363 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1364 stored or loaded (each MPI process part of the matrix must have less than `PETSC_INT_MAX` nonzeros). Since the total nonzero count in this 1365 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1366 1367 PETSc automatically does the byte swapping for 1368 machines that store the bytes reversed. Thus if you write your own binary 1369 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1370 and `PetscBinaryWrite()` to see how this may be done. 1371 1372 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1373 Each processor's chunk is loaded independently by its owning MPI process. 1374 Multiple objects, both matrices and vectors, can be stored within the same file. 1375 They are looked up by their PetscObject name. 1376 1377 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1378 by default the same structure and naming of the AIJ arrays and column count 1379 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1380 .vb 1381 save example.mat A b -v7.3 1382 .ve 1383 can be directly read by this routine (see Reference 1 for details). 1384 1385 Depending on your MATLAB version, this format might be a default, 1386 otherwise you can set it as default in Preferences. 1387 1388 Unless -nocompression flag is used to save the file in MATLAB, 1389 PETSc must be configured with ZLIB package. 1390 1391 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1392 1393 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1394 1395 Corresponding `MatView()` is not yet implemented. 1396 1397 The loaded matrix is actually a transpose of the original one in MATLAB, 1398 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1399 With this format, matrix is automatically transposed by PETSc, 1400 unless the matrix is marked as SPD or symmetric 1401 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1402 1403 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1404 1405 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1406 @*/ 1407 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1408 { 1409 PetscBool flg; 1410 1411 PetscFunctionBegin; 1412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1413 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1414 1415 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1416 1417 flg = PETSC_FALSE; 1418 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1419 if (flg) { 1420 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1421 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1422 } 1423 flg = PETSC_FALSE; 1424 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1425 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1426 1427 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1428 PetscUseTypeMethod(mat, load, viewer); 1429 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1430 PetscFunctionReturn(PETSC_SUCCESS); 1431 } 1432 1433 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1434 { 1435 Mat_Redundant *redund = *redundant; 1436 1437 PetscFunctionBegin; 1438 if (redund) { 1439 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1440 PetscCall(ISDestroy(&redund->isrow)); 1441 PetscCall(ISDestroy(&redund->iscol)); 1442 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1443 } else { 1444 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1445 PetscCall(PetscFree(redund->sbuf_j)); 1446 PetscCall(PetscFree(redund->sbuf_a)); 1447 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1448 PetscCall(PetscFree(redund->rbuf_j[i])); 1449 PetscCall(PetscFree(redund->rbuf_a[i])); 1450 } 1451 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1452 } 1453 1454 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1455 PetscCall(PetscFree(redund)); 1456 } 1457 PetscFunctionReturn(PETSC_SUCCESS); 1458 } 1459 1460 /*@ 1461 MatDestroy - Frees space taken by a matrix. 1462 1463 Collective 1464 1465 Input Parameter: 1466 . A - the matrix 1467 1468 Level: beginner 1469 1470 Developer Note: 1471 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1472 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1473 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1474 if changes are needed here. 1475 1476 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1477 @*/ 1478 PetscErrorCode MatDestroy(Mat *A) 1479 { 1480 PetscFunctionBegin; 1481 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1482 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1483 if (--((PetscObject)*A)->refct > 0) { 1484 *A = NULL; 1485 PetscFunctionReturn(PETSC_SUCCESS); 1486 } 1487 1488 /* if memory was published with SAWs then destroy it */ 1489 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1490 PetscTryTypeMethod(*A, destroy); 1491 1492 PetscCall(PetscFree((*A)->factorprefix)); 1493 PetscCall(PetscFree((*A)->defaultvectype)); 1494 PetscCall(PetscFree((*A)->defaultrandtype)); 1495 PetscCall(PetscFree((*A)->bsizes)); 1496 PetscCall(PetscFree((*A)->solvertype)); 1497 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1498 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1499 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1500 PetscCall(MatProductClear(*A)); 1501 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1502 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1503 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1504 PetscCall(MatDestroy(&(*A)->schur)); 1505 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1506 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1507 PetscCall(PetscHeaderDestroy(A)); 1508 PetscFunctionReturn(PETSC_SUCCESS); 1509 } 1510 1511 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1512 /*@ 1513 MatSetValues - Inserts or adds a block of values into a matrix. 1514 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1515 MUST be called after all calls to `MatSetValues()` have been completed. 1516 1517 Not Collective 1518 1519 Input Parameters: 1520 + mat - the matrix 1521 . v - a logically two-dimensional array of values 1522 . m - the number of rows 1523 . idxm - the global indices of the rows 1524 . n - the number of columns 1525 . idxn - the global indices of the columns 1526 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1527 1528 Level: beginner 1529 1530 Notes: 1531 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1532 1533 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1534 options cannot be mixed without intervening calls to the assembly 1535 routines. 1536 1537 `MatSetValues()` uses 0-based row and column numbers in Fortran 1538 as well as in C. 1539 1540 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1541 simply ignored. This allows easily inserting element stiffness matrices 1542 with homogeneous Dirichlet boundary conditions that you don't want represented 1543 in the matrix. 1544 1545 Efficiency Alert: 1546 The routine `MatSetValuesBlocked()` may offer much better efficiency 1547 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1548 1549 Fortran Notes: 1550 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1551 .vb 1552 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1553 .ve 1554 1555 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1556 1557 Developer Note: 1558 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1559 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1560 1561 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1562 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1563 @*/ 1564 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1565 { 1566 PetscFunctionBeginHot; 1567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1568 PetscValidType(mat, 1); 1569 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1570 PetscAssertPointer(idxm, 3); 1571 PetscAssertPointer(idxn, 5); 1572 MatCheckPreallocated(mat, 1); 1573 1574 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1575 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1576 1577 if (PetscDefined(USE_DEBUG)) { 1578 PetscInt i, j; 1579 1580 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1581 if (v) { 1582 for (i = 0; i < m; i++) { 1583 for (j = 0; j < n; j++) { 1584 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1585 #if defined(PETSC_USE_COMPLEX) 1586 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1587 #else 1588 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1589 #endif 1590 } 1591 } 1592 } 1593 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1594 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1595 } 1596 1597 if (mat->assembled) { 1598 mat->was_assembled = PETSC_TRUE; 1599 mat->assembled = PETSC_FALSE; 1600 } 1601 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1602 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1603 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1604 PetscFunctionReturn(PETSC_SUCCESS); 1605 } 1606 1607 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1608 /*@ 1609 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1610 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1611 MUST be called after all calls to `MatSetValues()` have been completed. 1612 1613 Not Collective 1614 1615 Input Parameters: 1616 + mat - the matrix 1617 . v - a logically two-dimensional array of values 1618 . ism - the rows to provide 1619 . isn - the columns to provide 1620 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1621 1622 Level: beginner 1623 1624 Notes: 1625 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1626 1627 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1628 options cannot be mixed without intervening calls to the assembly 1629 routines. 1630 1631 `MatSetValues()` uses 0-based row and column numbers in Fortran 1632 as well as in C. 1633 1634 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1635 simply ignored. This allows easily inserting element stiffness matrices 1636 with homogeneous Dirichlet boundary conditions that you don't want represented 1637 in the matrix. 1638 1639 Efficiency Alert: 1640 The routine `MatSetValuesBlocked()` may offer much better efficiency 1641 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1642 1643 This is currently not optimized for any particular `ISType` 1644 1645 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1646 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1647 @*/ 1648 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1649 { 1650 PetscInt m, n; 1651 const PetscInt *rows, *cols; 1652 1653 PetscFunctionBeginHot; 1654 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1655 PetscCall(ISGetIndices(ism, &rows)); 1656 PetscCall(ISGetIndices(isn, &cols)); 1657 PetscCall(ISGetLocalSize(ism, &m)); 1658 PetscCall(ISGetLocalSize(isn, &n)); 1659 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1660 PetscCall(ISRestoreIndices(ism, &rows)); 1661 PetscCall(ISRestoreIndices(isn, &cols)); 1662 PetscFunctionReturn(PETSC_SUCCESS); 1663 } 1664 1665 /*@ 1666 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1667 values into a matrix 1668 1669 Not Collective 1670 1671 Input Parameters: 1672 + mat - the matrix 1673 . row - the (block) row to set 1674 - v - a logically two-dimensional array of values 1675 1676 Level: intermediate 1677 1678 Notes: 1679 The values, `v`, are column-oriented (for the block version) and sorted 1680 1681 All the nonzero values in `row` must be provided 1682 1683 The matrix must have previously had its column indices set, likely by having been assembled. 1684 1685 `row` must belong to this MPI process 1686 1687 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1688 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1689 @*/ 1690 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1691 { 1692 PetscInt globalrow; 1693 1694 PetscFunctionBegin; 1695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1696 PetscValidType(mat, 1); 1697 PetscAssertPointer(v, 3); 1698 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1699 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1700 PetscFunctionReturn(PETSC_SUCCESS); 1701 } 1702 1703 /*@ 1704 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1705 values into a matrix 1706 1707 Not Collective 1708 1709 Input Parameters: 1710 + mat - the matrix 1711 . row - the (block) row to set 1712 - v - a logically two-dimensional (column major) array of values for block matrices with blocksize larger than one, otherwise a one dimensional array of values 1713 1714 Level: advanced 1715 1716 Notes: 1717 The values, `v`, are column-oriented for the block version. 1718 1719 All the nonzeros in `row` must be provided 1720 1721 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1722 1723 `row` must belong to this process 1724 1725 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1726 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1727 @*/ 1728 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1729 { 1730 PetscFunctionBeginHot; 1731 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1732 PetscValidType(mat, 1); 1733 MatCheckPreallocated(mat, 1); 1734 PetscAssertPointer(v, 3); 1735 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1736 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1737 mat->insertmode = INSERT_VALUES; 1738 1739 if (mat->assembled) { 1740 mat->was_assembled = PETSC_TRUE; 1741 mat->assembled = PETSC_FALSE; 1742 } 1743 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1744 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1745 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1746 PetscFunctionReturn(PETSC_SUCCESS); 1747 } 1748 1749 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1750 /*@ 1751 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1752 Using structured grid indexing 1753 1754 Not Collective 1755 1756 Input Parameters: 1757 + mat - the matrix 1758 . m - number of rows being entered 1759 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1760 . n - number of columns being entered 1761 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1762 . v - a logically two-dimensional array of values 1763 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1764 1765 Level: beginner 1766 1767 Notes: 1768 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1769 1770 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1771 options cannot be mixed without intervening calls to the assembly 1772 routines. 1773 1774 The grid coordinates are across the entire grid, not just the local portion 1775 1776 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1777 as well as in C. 1778 1779 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1780 1781 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1782 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1783 1784 The columns and rows in the stencil passed in MUST be contained within the 1785 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1786 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1787 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1788 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1789 1790 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1791 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1792 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1793 `DM_BOUNDARY_PERIODIC` boundary type. 1794 1795 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1796 a single value per point) you can skip filling those indices. 1797 1798 Inspired by the structured grid interface to the HYPRE package 1799 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1800 1801 Efficiency Alert: 1802 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1803 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1804 1805 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1806 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1807 @*/ 1808 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1809 { 1810 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1811 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1812 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1813 1814 PetscFunctionBegin; 1815 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1816 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1817 PetscValidType(mat, 1); 1818 PetscAssertPointer(idxm, 3); 1819 PetscAssertPointer(idxn, 5); 1820 1821 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1822 jdxm = buf; 1823 jdxn = buf + m; 1824 } else { 1825 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1826 jdxm = bufm; 1827 jdxn = bufn; 1828 } 1829 for (i = 0; i < m; i++) { 1830 for (j = 0; j < 3 - sdim; j++) dxm++; 1831 tmp = *dxm++ - starts[0]; 1832 for (j = 0; j < dim - 1; j++) { 1833 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1834 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1835 } 1836 if (mat->stencil.noc) dxm++; 1837 jdxm[i] = tmp; 1838 } 1839 for (i = 0; i < n; i++) { 1840 for (j = 0; j < 3 - sdim; j++) dxn++; 1841 tmp = *dxn++ - starts[0]; 1842 for (j = 0; j < dim - 1; j++) { 1843 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1844 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1845 } 1846 if (mat->stencil.noc) dxn++; 1847 jdxn[i] = tmp; 1848 } 1849 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1850 PetscCall(PetscFree2(bufm, bufn)); 1851 PetscFunctionReturn(PETSC_SUCCESS); 1852 } 1853 1854 /*@ 1855 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1856 Using structured grid indexing 1857 1858 Not Collective 1859 1860 Input Parameters: 1861 + mat - the matrix 1862 . m - number of rows being entered 1863 . idxm - grid coordinates for matrix rows being entered 1864 . n - number of columns being entered 1865 . idxn - grid coordinates for matrix columns being entered 1866 . v - a logically two-dimensional array of values 1867 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1868 1869 Level: beginner 1870 1871 Notes: 1872 By default the values, `v`, are row-oriented and unsorted. 1873 See `MatSetOption()` for other options. 1874 1875 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1876 options cannot be mixed without intervening calls to the assembly 1877 routines. 1878 1879 The grid coordinates are across the entire grid, not just the local portion 1880 1881 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1882 as well as in C. 1883 1884 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1885 1886 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1887 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1888 1889 The columns and rows in the stencil passed in MUST be contained within the 1890 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1891 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1892 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1893 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1894 1895 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1896 simply ignored. This allows easily inserting element stiffness matrices 1897 with homogeneous Dirichlet boundary conditions that you don't want represented 1898 in the matrix. 1899 1900 Inspired by the structured grid interface to the HYPRE package 1901 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1902 1903 Fortran Note: 1904 `idxm` and `idxn` should be declared as 1905 .vb 1906 MatStencil idxm(4,m),idxn(4,n) 1907 .ve 1908 and the values inserted using 1909 .vb 1910 idxm(MatStencil_i,1) = i 1911 idxm(MatStencil_j,1) = j 1912 idxm(MatStencil_k,1) = k 1913 etc 1914 .ve 1915 1916 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1917 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1918 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1919 @*/ 1920 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1921 { 1922 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1923 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1924 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1925 1926 PetscFunctionBegin; 1927 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1928 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1929 PetscValidType(mat, 1); 1930 PetscAssertPointer(idxm, 3); 1931 PetscAssertPointer(idxn, 5); 1932 PetscAssertPointer(v, 6); 1933 1934 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1935 jdxm = buf; 1936 jdxn = buf + m; 1937 } else { 1938 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1939 jdxm = bufm; 1940 jdxn = bufn; 1941 } 1942 for (i = 0; i < m; i++) { 1943 for (j = 0; j < 3 - sdim; j++) dxm++; 1944 tmp = *dxm++ - starts[0]; 1945 for (j = 0; j < sdim - 1; j++) { 1946 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1947 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1948 } 1949 dxm++; 1950 jdxm[i] = tmp; 1951 } 1952 for (i = 0; i < n; i++) { 1953 for (j = 0; j < 3 - sdim; j++) dxn++; 1954 tmp = *dxn++ - starts[0]; 1955 for (j = 0; j < sdim - 1; j++) { 1956 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1957 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1958 } 1959 dxn++; 1960 jdxn[i] = tmp; 1961 } 1962 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1963 PetscCall(PetscFree2(bufm, bufn)); 1964 PetscFunctionReturn(PETSC_SUCCESS); 1965 } 1966 1967 /*@ 1968 MatSetStencil - Sets the grid information for setting values into a matrix via 1969 `MatSetValuesStencil()` 1970 1971 Not Collective 1972 1973 Input Parameters: 1974 + mat - the matrix 1975 . dim - dimension of the grid 1, 2, or 3 1976 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1977 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1978 - dof - number of degrees of freedom per node 1979 1980 Level: beginner 1981 1982 Notes: 1983 Inspired by the structured grid interface to the HYPRE package 1984 (www.llnl.gov/CASC/hyper) 1985 1986 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1987 user. 1988 1989 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1990 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1991 @*/ 1992 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1993 { 1994 PetscFunctionBegin; 1995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1996 PetscAssertPointer(dims, 3); 1997 PetscAssertPointer(starts, 4); 1998 1999 mat->stencil.dim = dim + (dof > 1); 2000 for (PetscInt i = 0; i < dim; i++) { 2001 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2002 mat->stencil.starts[i] = starts[dim - i - 1]; 2003 } 2004 mat->stencil.dims[dim] = dof; 2005 mat->stencil.starts[dim] = 0; 2006 mat->stencil.noc = (PetscBool)(dof == 1); 2007 PetscFunctionReturn(PETSC_SUCCESS); 2008 } 2009 2010 /*@ 2011 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2012 2013 Not Collective 2014 2015 Input Parameters: 2016 + mat - the matrix 2017 . v - a logically two-dimensional array of values 2018 . m - the number of block rows 2019 . idxm - the global block indices 2020 . n - the number of block columns 2021 . idxn - the global block indices 2022 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2023 2024 Level: intermediate 2025 2026 Notes: 2027 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2028 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2029 2030 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2031 NOT the total number of rows/columns; for example, if the block size is 2 and 2032 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2033 The values in `idxm` would be 1 2; that is the first index for each block divided by 2034 the block size. 2035 2036 You must call `MatSetBlockSize()` when constructing this matrix (before 2037 preallocating it). 2038 2039 By default the values, `v`, are row-oriented, so the layout of 2040 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2041 2042 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2043 options cannot be mixed without intervening calls to the assembly 2044 routines. 2045 2046 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2047 as well as in C. 2048 2049 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2050 simply ignored. This allows easily inserting element stiffness matrices 2051 with homogeneous Dirichlet boundary conditions that you don't want represented 2052 in the matrix. 2053 2054 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2055 internal searching must be done to determine where to place the 2056 data in the matrix storage space. By instead inserting blocks of 2057 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2058 reduced. 2059 2060 Example: 2061 .vb 2062 Suppose m=n=2 and block size(bs) = 2 The array is 2063 2064 1 2 | 3 4 2065 5 6 | 7 8 2066 - - - | - - - 2067 9 10 | 11 12 2068 13 14 | 15 16 2069 2070 v[] should be passed in like 2071 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2072 2073 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2074 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2075 .ve 2076 2077 Fortran Notes: 2078 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2079 .vb 2080 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2081 .ve 2082 2083 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2084 2085 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2086 @*/ 2087 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2088 { 2089 PetscFunctionBeginHot; 2090 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2091 PetscValidType(mat, 1); 2092 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2093 PetscAssertPointer(idxm, 3); 2094 PetscAssertPointer(idxn, 5); 2095 MatCheckPreallocated(mat, 1); 2096 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2097 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2098 if (PetscDefined(USE_DEBUG)) { 2099 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2100 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2101 } 2102 if (PetscDefined(USE_DEBUG)) { 2103 PetscInt rbs, cbs, M, N, i; 2104 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2105 PetscCall(MatGetSize(mat, &M, &N)); 2106 for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than row length %" PetscInt_FMT, i, idxm[i], rbs, M); 2107 for (i = 0; i < n; i++) 2108 PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block %" PetscInt_FMT " contains an index %" PetscInt_FMT "*%" PetscInt_FMT " greater than column length %" PetscInt_FMT, i, idxn[i], cbs, N); 2109 } 2110 if (mat->assembled) { 2111 mat->was_assembled = PETSC_TRUE; 2112 mat->assembled = PETSC_FALSE; 2113 } 2114 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2115 if (mat->ops->setvaluesblocked) { 2116 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2117 } else { 2118 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2119 PetscInt i, j, bs, cbs; 2120 2121 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2122 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2123 iidxm = buf; 2124 iidxn = buf + m * bs; 2125 } else { 2126 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2127 iidxm = bufr; 2128 iidxn = bufc; 2129 } 2130 for (i = 0; i < m; i++) { 2131 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2132 } 2133 if (m != n || bs != cbs || idxm != idxn) { 2134 for (i = 0; i < n; i++) { 2135 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2136 } 2137 } else iidxn = iidxm; 2138 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2139 PetscCall(PetscFree2(bufr, bufc)); 2140 } 2141 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2142 PetscFunctionReturn(PETSC_SUCCESS); 2143 } 2144 2145 /*@ 2146 MatGetValues - Gets a block of local values from a matrix. 2147 2148 Not Collective; can only return values that are owned by the give process 2149 2150 Input Parameters: 2151 + mat - the matrix 2152 . v - a logically two-dimensional array for storing the values 2153 . m - the number of rows 2154 . idxm - the global indices of the rows 2155 . n - the number of columns 2156 - idxn - the global indices of the columns 2157 2158 Level: advanced 2159 2160 Notes: 2161 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2162 The values, `v`, are then returned in a row-oriented format, 2163 analogous to that used by default in `MatSetValues()`. 2164 2165 `MatGetValues()` uses 0-based row and column numbers in 2166 Fortran as well as in C. 2167 2168 `MatGetValues()` requires that the matrix has been assembled 2169 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2170 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2171 without intermediate matrix assembly. 2172 2173 Negative row or column indices will be ignored and those locations in `v` will be 2174 left unchanged. 2175 2176 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2177 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2178 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2179 2180 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2181 @*/ 2182 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2183 { 2184 PetscFunctionBegin; 2185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2186 PetscValidType(mat, 1); 2187 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2188 PetscAssertPointer(idxm, 3); 2189 PetscAssertPointer(idxn, 5); 2190 PetscAssertPointer(v, 6); 2191 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2192 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2193 MatCheckPreallocated(mat, 1); 2194 2195 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2196 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2197 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2198 PetscFunctionReturn(PETSC_SUCCESS); 2199 } 2200 2201 /*@ 2202 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2203 defined previously by `MatSetLocalToGlobalMapping()` 2204 2205 Not Collective 2206 2207 Input Parameters: 2208 + mat - the matrix 2209 . nrow - number of rows 2210 . irow - the row local indices 2211 . ncol - number of columns 2212 - icol - the column local indices 2213 2214 Output Parameter: 2215 . y - a logically two-dimensional array of values 2216 2217 Level: advanced 2218 2219 Notes: 2220 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2221 2222 This routine can only return values that are owned by the requesting MPI process. That is, for standard matrix formats, rows that, in the global numbering, 2223 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2224 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2225 with `MatSetLocalToGlobalMapping()`. 2226 2227 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2228 `MatSetValuesLocal()`, `MatGetValues()` 2229 @*/ 2230 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2231 { 2232 PetscFunctionBeginHot; 2233 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2234 PetscValidType(mat, 1); 2235 MatCheckPreallocated(mat, 1); 2236 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2237 PetscAssertPointer(irow, 3); 2238 PetscAssertPointer(icol, 5); 2239 if (PetscDefined(USE_DEBUG)) { 2240 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2241 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2242 } 2243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2244 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2245 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2246 else { 2247 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2248 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2249 irowm = buf; 2250 icolm = buf + nrow; 2251 } else { 2252 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2253 irowm = bufr; 2254 icolm = bufc; 2255 } 2256 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2257 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2258 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2259 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2260 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2261 PetscCall(PetscFree2(bufr, bufc)); 2262 } 2263 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2264 PetscFunctionReturn(PETSC_SUCCESS); 2265 } 2266 2267 /*@ 2268 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2269 the same size. Currently, this can only be called once and creates the given matrix. 2270 2271 Not Collective 2272 2273 Input Parameters: 2274 + mat - the matrix 2275 . nb - the number of blocks 2276 . bs - the number of rows (and columns) in each block 2277 . rows - a concatenation of the rows for each block 2278 - v - a concatenation of logically two-dimensional arrays of values 2279 2280 Level: advanced 2281 2282 Notes: 2283 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2284 2285 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2286 2287 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2288 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2289 @*/ 2290 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2291 { 2292 PetscFunctionBegin; 2293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2294 PetscValidType(mat, 1); 2295 PetscAssertPointer(rows, 4); 2296 PetscAssertPointer(v, 5); 2297 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2298 2299 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2300 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2301 else { 2302 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2303 } 2304 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2305 PetscFunctionReturn(PETSC_SUCCESS); 2306 } 2307 2308 /*@ 2309 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2310 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2311 using a local (per-processor) numbering. 2312 2313 Not Collective 2314 2315 Input Parameters: 2316 + x - the matrix 2317 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2318 - cmapping - column mapping 2319 2320 Level: intermediate 2321 2322 Note: 2323 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2324 2325 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2326 @*/ 2327 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2328 { 2329 PetscFunctionBegin; 2330 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2331 PetscValidType(x, 1); 2332 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2333 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2334 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2335 else { 2336 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2337 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2338 } 2339 PetscFunctionReturn(PETSC_SUCCESS); 2340 } 2341 2342 /*@ 2343 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2344 2345 Not Collective 2346 2347 Input Parameter: 2348 . A - the matrix 2349 2350 Output Parameters: 2351 + rmapping - row mapping 2352 - cmapping - column mapping 2353 2354 Level: advanced 2355 2356 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2357 @*/ 2358 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2359 { 2360 PetscFunctionBegin; 2361 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2362 PetscValidType(A, 1); 2363 if (rmapping) { 2364 PetscAssertPointer(rmapping, 2); 2365 *rmapping = A->rmap->mapping; 2366 } 2367 if (cmapping) { 2368 PetscAssertPointer(cmapping, 3); 2369 *cmapping = A->cmap->mapping; 2370 } 2371 PetscFunctionReturn(PETSC_SUCCESS); 2372 } 2373 2374 /*@ 2375 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2376 2377 Logically Collective 2378 2379 Input Parameters: 2380 + A - the matrix 2381 . rmap - row layout 2382 - cmap - column layout 2383 2384 Level: advanced 2385 2386 Note: 2387 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2388 2389 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2390 @*/ 2391 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2392 { 2393 PetscFunctionBegin; 2394 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2395 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2396 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2397 PetscFunctionReturn(PETSC_SUCCESS); 2398 } 2399 2400 /*@ 2401 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2402 2403 Not Collective 2404 2405 Input Parameter: 2406 . A - the matrix 2407 2408 Output Parameters: 2409 + rmap - row layout 2410 - cmap - column layout 2411 2412 Level: advanced 2413 2414 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2415 @*/ 2416 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2417 { 2418 PetscFunctionBegin; 2419 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2420 PetscValidType(A, 1); 2421 if (rmap) { 2422 PetscAssertPointer(rmap, 2); 2423 *rmap = A->rmap; 2424 } 2425 if (cmap) { 2426 PetscAssertPointer(cmap, 3); 2427 *cmap = A->cmap; 2428 } 2429 PetscFunctionReturn(PETSC_SUCCESS); 2430 } 2431 2432 /*@ 2433 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2434 using a local numbering of the rows and columns. 2435 2436 Not Collective 2437 2438 Input Parameters: 2439 + mat - the matrix 2440 . nrow - number of rows 2441 . irow - the row local indices 2442 . ncol - number of columns 2443 . icol - the column local indices 2444 . y - a logically two-dimensional array of values 2445 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2446 2447 Level: intermediate 2448 2449 Notes: 2450 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2451 2452 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2453 options cannot be mixed without intervening calls to the assembly 2454 routines. 2455 2456 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2457 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2458 2459 Fortran Notes: 2460 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2461 .vb 2462 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2463 .ve 2464 2465 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2466 2467 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2468 `MatGetValuesLocal()` 2469 @*/ 2470 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2471 { 2472 PetscFunctionBeginHot; 2473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2474 PetscValidType(mat, 1); 2475 MatCheckPreallocated(mat, 1); 2476 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2477 PetscAssertPointer(irow, 3); 2478 PetscAssertPointer(icol, 5); 2479 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2480 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2481 if (PetscDefined(USE_DEBUG)) { 2482 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2483 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2484 } 2485 2486 if (mat->assembled) { 2487 mat->was_assembled = PETSC_TRUE; 2488 mat->assembled = PETSC_FALSE; 2489 } 2490 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2491 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2492 else { 2493 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2494 const PetscInt *irowm, *icolm; 2495 2496 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2497 bufr = buf; 2498 bufc = buf + nrow; 2499 irowm = bufr; 2500 icolm = bufc; 2501 } else { 2502 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2503 irowm = bufr; 2504 icolm = bufc; 2505 } 2506 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2507 else irowm = irow; 2508 if (mat->cmap->mapping) { 2509 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2510 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2511 } else icolm = irowm; 2512 } else icolm = icol; 2513 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2514 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2515 } 2516 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2517 PetscFunctionReturn(PETSC_SUCCESS); 2518 } 2519 2520 /*@ 2521 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2522 using a local ordering of the nodes a block at a time. 2523 2524 Not Collective 2525 2526 Input Parameters: 2527 + mat - the matrix 2528 . nrow - number of rows 2529 . irow - the row local indices 2530 . ncol - number of columns 2531 . icol - the column local indices 2532 . y - a logically two-dimensional array of values 2533 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2534 2535 Level: intermediate 2536 2537 Notes: 2538 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2539 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2540 2541 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2542 options cannot be mixed without intervening calls to the assembly 2543 routines. 2544 2545 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2546 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2547 2548 Fortran Notes: 2549 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2550 .vb 2551 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2552 .ve 2553 2554 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2555 2556 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2557 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2558 @*/ 2559 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2560 { 2561 PetscFunctionBeginHot; 2562 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2563 PetscValidType(mat, 1); 2564 MatCheckPreallocated(mat, 1); 2565 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2566 PetscAssertPointer(irow, 3); 2567 PetscAssertPointer(icol, 5); 2568 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2569 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2570 if (PetscDefined(USE_DEBUG)) { 2571 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2572 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2573 } 2574 2575 if (mat->assembled) { 2576 mat->was_assembled = PETSC_TRUE; 2577 mat->assembled = PETSC_FALSE; 2578 } 2579 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2580 PetscInt irbs, rbs; 2581 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2582 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2583 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2584 } 2585 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2586 PetscInt icbs, cbs; 2587 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2588 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2589 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2590 } 2591 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2592 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2593 else { 2594 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2595 const PetscInt *irowm, *icolm; 2596 2597 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2598 bufr = buf; 2599 bufc = buf + nrow; 2600 irowm = bufr; 2601 icolm = bufc; 2602 } else { 2603 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2604 irowm = bufr; 2605 icolm = bufc; 2606 } 2607 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2608 else irowm = irow; 2609 if (mat->cmap->mapping) { 2610 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2611 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2612 } else icolm = irowm; 2613 } else icolm = icol; 2614 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2615 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2616 } 2617 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2618 PetscFunctionReturn(PETSC_SUCCESS); 2619 } 2620 2621 /*@ 2622 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2623 2624 Collective 2625 2626 Input Parameters: 2627 + mat - the matrix 2628 - x - the vector to be multiplied 2629 2630 Output Parameter: 2631 . y - the result 2632 2633 Level: developer 2634 2635 Note: 2636 The vectors `x` and `y` cannot be the same. I.e., one cannot 2637 call `MatMultDiagonalBlock`(A,y,y). 2638 2639 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2640 @*/ 2641 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2642 { 2643 PetscFunctionBegin; 2644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2645 PetscValidType(mat, 1); 2646 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2647 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2648 2649 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2650 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2651 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2652 MatCheckPreallocated(mat, 1); 2653 2654 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2655 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2656 PetscFunctionReturn(PETSC_SUCCESS); 2657 } 2658 2659 /*@ 2660 MatMult - Computes the matrix-vector product, $y = Ax$. 2661 2662 Neighbor-wise Collective 2663 2664 Input Parameters: 2665 + mat - the matrix 2666 - x - the vector to be multiplied 2667 2668 Output Parameter: 2669 . y - the result 2670 2671 Level: beginner 2672 2673 Note: 2674 The vectors `x` and `y` cannot be the same. I.e., one cannot 2675 call `MatMult`(A,y,y). 2676 2677 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2678 @*/ 2679 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2680 { 2681 PetscFunctionBegin; 2682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2683 PetscValidType(mat, 1); 2684 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2685 VecCheckAssembled(x); 2686 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2687 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2688 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2689 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2690 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2691 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2692 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2693 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2694 PetscCall(VecSetErrorIfLocked(y, 3)); 2695 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2696 MatCheckPreallocated(mat, 1); 2697 2698 PetscCall(VecLockReadPush(x)); 2699 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2700 PetscUseTypeMethod(mat, mult, x, y); 2701 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2702 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2703 PetscCall(VecLockReadPop(x)); 2704 PetscFunctionReturn(PETSC_SUCCESS); 2705 } 2706 2707 /*@ 2708 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2709 2710 Neighbor-wise Collective 2711 2712 Input Parameters: 2713 + mat - the matrix 2714 - x - the vector to be multiplied 2715 2716 Output Parameter: 2717 . y - the result 2718 2719 Level: beginner 2720 2721 Notes: 2722 The vectors `x` and `y` cannot be the same. I.e., one cannot 2723 call `MatMultTranspose`(A,y,y). 2724 2725 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2726 use `MatMultHermitianTranspose()` 2727 2728 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2729 @*/ 2730 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2731 { 2732 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2733 2734 PetscFunctionBegin; 2735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2736 PetscValidType(mat, 1); 2737 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2738 VecCheckAssembled(x); 2739 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2740 2741 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2742 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2743 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2744 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2745 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2746 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2747 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2748 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2749 MatCheckPreallocated(mat, 1); 2750 2751 if (!mat->ops->multtranspose) { 2752 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2753 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2754 } else op = mat->ops->multtranspose; 2755 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2756 PetscCall(VecLockReadPush(x)); 2757 PetscCall((*op)(mat, x, y)); 2758 PetscCall(VecLockReadPop(x)); 2759 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2760 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2761 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2762 PetscFunctionReturn(PETSC_SUCCESS); 2763 } 2764 2765 /*@ 2766 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2767 2768 Neighbor-wise Collective 2769 2770 Input Parameters: 2771 + mat - the matrix 2772 - x - the vector to be multiplied 2773 2774 Output Parameter: 2775 . y - the result 2776 2777 Level: beginner 2778 2779 Notes: 2780 The vectors `x` and `y` cannot be the same. I.e., one cannot 2781 call `MatMultHermitianTranspose`(A,y,y). 2782 2783 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2784 2785 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2786 2787 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2788 @*/ 2789 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2790 { 2791 PetscFunctionBegin; 2792 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2793 PetscValidType(mat, 1); 2794 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2795 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2796 2797 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2799 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2800 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2801 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2802 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2803 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2804 MatCheckPreallocated(mat, 1); 2805 2806 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2807 #if defined(PETSC_USE_COMPLEX) 2808 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2809 PetscCall(VecLockReadPush(x)); 2810 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2811 else PetscUseTypeMethod(mat, mult, x, y); 2812 PetscCall(VecLockReadPop(x)); 2813 } else { 2814 Vec w; 2815 PetscCall(VecDuplicate(x, &w)); 2816 PetscCall(VecCopy(x, w)); 2817 PetscCall(VecConjugate(w)); 2818 PetscCall(MatMultTranspose(mat, w, y)); 2819 PetscCall(VecDestroy(&w)); 2820 PetscCall(VecConjugate(y)); 2821 } 2822 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2823 #else 2824 PetscCall(MatMultTranspose(mat, x, y)); 2825 #endif 2826 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2827 PetscFunctionReturn(PETSC_SUCCESS); 2828 } 2829 2830 /*@ 2831 MatMultAdd - Computes $v3 = v2 + A * v1$. 2832 2833 Neighbor-wise Collective 2834 2835 Input Parameters: 2836 + mat - the matrix 2837 . v1 - the vector to be multiplied by `mat` 2838 - v2 - the vector to be added to the result 2839 2840 Output Parameter: 2841 . v3 - the result 2842 2843 Level: beginner 2844 2845 Note: 2846 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2847 call `MatMultAdd`(A,v1,v2,v1). 2848 2849 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2850 @*/ 2851 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2852 { 2853 PetscFunctionBegin; 2854 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2855 PetscValidType(mat, 1); 2856 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2857 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2858 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2859 2860 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2861 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2862 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2863 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2864 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2865 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2866 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2867 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2868 MatCheckPreallocated(mat, 1); 2869 2870 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2871 PetscCall(VecLockReadPush(v1)); 2872 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2873 PetscCall(VecLockReadPop(v1)); 2874 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2875 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2876 PetscFunctionReturn(PETSC_SUCCESS); 2877 } 2878 2879 /*@ 2880 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2881 2882 Neighbor-wise Collective 2883 2884 Input Parameters: 2885 + mat - the matrix 2886 . v1 - the vector to be multiplied by the transpose of the matrix 2887 - v2 - the vector to be added to the result 2888 2889 Output Parameter: 2890 . v3 - the result 2891 2892 Level: beginner 2893 2894 Note: 2895 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2896 call `MatMultTransposeAdd`(A,v1,v2,v1). 2897 2898 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2899 @*/ 2900 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2901 { 2902 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2903 2904 PetscFunctionBegin; 2905 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2906 PetscValidType(mat, 1); 2907 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2908 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2909 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2910 2911 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2912 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2913 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2914 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2915 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2916 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2917 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2918 MatCheckPreallocated(mat, 1); 2919 2920 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2921 PetscCall(VecLockReadPush(v1)); 2922 PetscCall((*op)(mat, v1, v2, v3)); 2923 PetscCall(VecLockReadPop(v1)); 2924 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2925 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2926 PetscFunctionReturn(PETSC_SUCCESS); 2927 } 2928 2929 /*@ 2930 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2931 2932 Neighbor-wise Collective 2933 2934 Input Parameters: 2935 + mat - the matrix 2936 . v1 - the vector to be multiplied by the Hermitian transpose 2937 - v2 - the vector to be added to the result 2938 2939 Output Parameter: 2940 . v3 - the result 2941 2942 Level: beginner 2943 2944 Note: 2945 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2946 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2947 2948 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2949 @*/ 2950 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2951 { 2952 PetscFunctionBegin; 2953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2954 PetscValidType(mat, 1); 2955 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2956 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2957 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2958 2959 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2960 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2961 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2962 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2963 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2964 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2965 MatCheckPreallocated(mat, 1); 2966 2967 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2968 PetscCall(VecLockReadPush(v1)); 2969 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2970 else { 2971 Vec w, z; 2972 PetscCall(VecDuplicate(v1, &w)); 2973 PetscCall(VecCopy(v1, w)); 2974 PetscCall(VecConjugate(w)); 2975 PetscCall(VecDuplicate(v3, &z)); 2976 PetscCall(MatMultTranspose(mat, w, z)); 2977 PetscCall(VecDestroy(&w)); 2978 PetscCall(VecConjugate(z)); 2979 if (v2 != v3) { 2980 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2981 } else { 2982 PetscCall(VecAXPY(v3, 1.0, z)); 2983 } 2984 PetscCall(VecDestroy(&z)); 2985 } 2986 PetscCall(VecLockReadPop(v1)); 2987 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2988 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2989 PetscFunctionReturn(PETSC_SUCCESS); 2990 } 2991 2992 /*@ 2993 MatGetFactorType - gets the type of factorization a matrix is 2994 2995 Not Collective 2996 2997 Input Parameter: 2998 . mat - the matrix 2999 3000 Output Parameter: 3001 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3002 3003 Level: intermediate 3004 3005 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3006 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3007 @*/ 3008 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3009 { 3010 PetscFunctionBegin; 3011 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3012 PetscValidType(mat, 1); 3013 PetscAssertPointer(t, 2); 3014 *t = mat->factortype; 3015 PetscFunctionReturn(PETSC_SUCCESS); 3016 } 3017 3018 /*@ 3019 MatSetFactorType - sets the type of factorization a matrix is 3020 3021 Logically Collective 3022 3023 Input Parameters: 3024 + mat - the matrix 3025 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3026 3027 Level: intermediate 3028 3029 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3030 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3031 @*/ 3032 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3033 { 3034 PetscFunctionBegin; 3035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3036 PetscValidType(mat, 1); 3037 mat->factortype = t; 3038 PetscFunctionReturn(PETSC_SUCCESS); 3039 } 3040 3041 /*@ 3042 MatGetInfo - Returns information about matrix storage (number of 3043 nonzeros, memory, etc.). 3044 3045 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3046 3047 Input Parameters: 3048 + mat - the matrix 3049 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 3050 3051 Output Parameter: 3052 . info - matrix information context 3053 3054 Options Database Key: 3055 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3056 3057 Level: intermediate 3058 3059 Notes: 3060 The `MatInfo` context contains a variety of matrix data, including 3061 number of nonzeros allocated and used, number of mallocs during 3062 matrix assembly, etc. Additional information for factored matrices 3063 is provided (such as the fill ratio, number of mallocs during 3064 factorization, etc.). 3065 3066 Example: 3067 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3068 data within the `MatInfo` context. For example, 3069 .vb 3070 MatInfo info; 3071 Mat A; 3072 double mal, nz_a, nz_u; 3073 3074 MatGetInfo(A, MAT_LOCAL, &info); 3075 mal = info.mallocs; 3076 nz_a = info.nz_allocated; 3077 .ve 3078 3079 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3080 @*/ 3081 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3082 { 3083 PetscFunctionBegin; 3084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3085 PetscValidType(mat, 1); 3086 PetscAssertPointer(info, 3); 3087 MatCheckPreallocated(mat, 1); 3088 PetscUseTypeMethod(mat, getinfo, flag, info); 3089 PetscFunctionReturn(PETSC_SUCCESS); 3090 } 3091 3092 /* 3093 This is used by external packages where it is not easy to get the info from the actual 3094 matrix factorization. 3095 */ 3096 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3097 { 3098 PetscFunctionBegin; 3099 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3100 PetscFunctionReturn(PETSC_SUCCESS); 3101 } 3102 3103 /*@ 3104 MatLUFactor - Performs in-place LU factorization of matrix. 3105 3106 Collective 3107 3108 Input Parameters: 3109 + mat - the matrix 3110 . row - row permutation 3111 . col - column permutation 3112 - info - options for factorization, includes 3113 .vb 3114 fill - expected fill as ratio of original fill. 3115 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3116 Run with the option -info to determine an optimal value to use 3117 .ve 3118 3119 Level: developer 3120 3121 Notes: 3122 Most users should employ the `KSP` interface for linear solvers 3123 instead of working directly with matrix algebra routines such as this. 3124 See, e.g., `KSPCreate()`. 3125 3126 This changes the state of the matrix to a factored matrix; it cannot be used 3127 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3128 3129 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3130 when not using `KSP`. 3131 3132 Fortran Note: 3133 A valid (non-null) `info` argument must be provided 3134 3135 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3136 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3137 @*/ 3138 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3139 { 3140 MatFactorInfo tinfo; 3141 3142 PetscFunctionBegin; 3143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3144 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3145 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3146 if (info) PetscAssertPointer(info, 4); 3147 PetscValidType(mat, 1); 3148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3150 MatCheckPreallocated(mat, 1); 3151 if (!info) { 3152 PetscCall(MatFactorInfoInitialize(&tinfo)); 3153 info = &tinfo; 3154 } 3155 3156 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3157 PetscUseTypeMethod(mat, lufactor, row, col, info); 3158 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3159 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3160 PetscFunctionReturn(PETSC_SUCCESS); 3161 } 3162 3163 /*@ 3164 MatILUFactor - Performs in-place ILU factorization of matrix. 3165 3166 Collective 3167 3168 Input Parameters: 3169 + mat - the matrix 3170 . row - row permutation 3171 . col - column permutation 3172 - info - structure containing 3173 .vb 3174 levels - number of levels of fill. 3175 expected fill - as ratio of original fill. 3176 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3177 missing diagonal entries) 3178 .ve 3179 3180 Level: developer 3181 3182 Notes: 3183 Most users should employ the `KSP` interface for linear solvers 3184 instead of working directly with matrix algebra routines such as this. 3185 See, e.g., `KSPCreate()`. 3186 3187 Probably really in-place only when level of fill is zero, otherwise allocates 3188 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3189 when not using `KSP`. 3190 3191 Fortran Note: 3192 A valid (non-null) `info` argument must be provided 3193 3194 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3195 @*/ 3196 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3197 { 3198 PetscFunctionBegin; 3199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3200 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3201 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3202 PetscAssertPointer(info, 4); 3203 PetscValidType(mat, 1); 3204 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3205 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3206 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3207 MatCheckPreallocated(mat, 1); 3208 3209 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3210 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3211 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3212 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3213 PetscFunctionReturn(PETSC_SUCCESS); 3214 } 3215 3216 /*@ 3217 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3218 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3219 3220 Collective 3221 3222 Input Parameters: 3223 + fact - the factor matrix obtained with `MatGetFactor()` 3224 . mat - the matrix 3225 . row - the row permutation 3226 . col - the column permutation 3227 - info - options for factorization, includes 3228 .vb 3229 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3230 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3231 .ve 3232 3233 Level: developer 3234 3235 Notes: 3236 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3237 3238 Most users should employ the simplified `KSP` interface for linear solvers 3239 instead of working directly with matrix algebra routines such as this. 3240 See, e.g., `KSPCreate()`. 3241 3242 Fortran Note: 3243 A valid (non-null) `info` argument must be provided 3244 3245 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3246 @*/ 3247 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3248 { 3249 MatFactorInfo tinfo; 3250 3251 PetscFunctionBegin; 3252 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3253 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3254 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3255 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3256 if (info) PetscAssertPointer(info, 5); 3257 PetscValidType(fact, 1); 3258 PetscValidType(mat, 2); 3259 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3260 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3261 MatCheckPreallocated(mat, 2); 3262 if (!info) { 3263 PetscCall(MatFactorInfoInitialize(&tinfo)); 3264 info = &tinfo; 3265 } 3266 3267 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3268 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3269 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3270 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3271 PetscFunctionReturn(PETSC_SUCCESS); 3272 } 3273 3274 /*@ 3275 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3276 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3277 3278 Collective 3279 3280 Input Parameters: 3281 + fact - the factor matrix obtained with `MatGetFactor()` 3282 . mat - the matrix 3283 - info - options for factorization 3284 3285 Level: developer 3286 3287 Notes: 3288 See `MatLUFactor()` for in-place factorization. See 3289 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3290 3291 Most users should employ the `KSP` interface for linear solvers 3292 instead of working directly with matrix algebra routines such as this. 3293 See, e.g., `KSPCreate()`. 3294 3295 Fortran Note: 3296 A valid (non-null) `info` argument must be provided 3297 3298 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3299 @*/ 3300 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3301 { 3302 MatFactorInfo tinfo; 3303 3304 PetscFunctionBegin; 3305 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3307 PetscValidType(fact, 1); 3308 PetscValidType(mat, 2); 3309 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3310 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3311 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3312 3313 MatCheckPreallocated(mat, 2); 3314 if (!info) { 3315 PetscCall(MatFactorInfoInitialize(&tinfo)); 3316 info = &tinfo; 3317 } 3318 3319 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3320 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3321 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3322 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3323 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3324 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3325 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3326 PetscFunctionReturn(PETSC_SUCCESS); 3327 } 3328 3329 /*@ 3330 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3331 symmetric matrix. 3332 3333 Collective 3334 3335 Input Parameters: 3336 + mat - the matrix 3337 . perm - row and column permutations 3338 - info - expected fill as ratio of original fill 3339 3340 Level: developer 3341 3342 Notes: 3343 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3344 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3345 3346 Most users should employ the `KSP` interface for linear solvers 3347 instead of working directly with matrix algebra routines such as this. 3348 See, e.g., `KSPCreate()`. 3349 3350 Fortran Note: 3351 A valid (non-null) `info` argument must be provided 3352 3353 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3354 `MatGetOrdering()` 3355 @*/ 3356 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3357 { 3358 MatFactorInfo tinfo; 3359 3360 PetscFunctionBegin; 3361 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3362 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3363 if (info) PetscAssertPointer(info, 3); 3364 PetscValidType(mat, 1); 3365 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3366 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3367 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3368 MatCheckPreallocated(mat, 1); 3369 if (!info) { 3370 PetscCall(MatFactorInfoInitialize(&tinfo)); 3371 info = &tinfo; 3372 } 3373 3374 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3375 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3376 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3377 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3378 PetscFunctionReturn(PETSC_SUCCESS); 3379 } 3380 3381 /*@ 3382 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3383 of a symmetric matrix. 3384 3385 Collective 3386 3387 Input Parameters: 3388 + fact - the factor matrix obtained with `MatGetFactor()` 3389 . mat - the matrix 3390 . perm - row and column permutations 3391 - info - options for factorization, includes 3392 .vb 3393 fill - expected fill as ratio of original fill. 3394 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3395 Run with the option -info to determine an optimal value to use 3396 .ve 3397 3398 Level: developer 3399 3400 Notes: 3401 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3402 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3403 3404 Most users should employ the `KSP` interface for linear solvers 3405 instead of working directly with matrix algebra routines such as this. 3406 See, e.g., `KSPCreate()`. 3407 3408 Fortran Note: 3409 A valid (non-null) `info` argument must be provided 3410 3411 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3412 `MatGetOrdering()` 3413 @*/ 3414 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3415 { 3416 MatFactorInfo tinfo; 3417 3418 PetscFunctionBegin; 3419 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3421 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3422 if (info) PetscAssertPointer(info, 4); 3423 PetscValidType(fact, 1); 3424 PetscValidType(mat, 2); 3425 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3426 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3427 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3428 MatCheckPreallocated(mat, 2); 3429 if (!info) { 3430 PetscCall(MatFactorInfoInitialize(&tinfo)); 3431 info = &tinfo; 3432 } 3433 3434 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3435 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3436 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3437 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3438 PetscFunctionReturn(PETSC_SUCCESS); 3439 } 3440 3441 /*@ 3442 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3443 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3444 `MatCholeskyFactorSymbolic()`. 3445 3446 Collective 3447 3448 Input Parameters: 3449 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3450 . mat - the initial matrix that is to be factored 3451 - info - options for factorization 3452 3453 Level: developer 3454 3455 Note: 3456 Most users should employ the `KSP` interface for linear solvers 3457 instead of working directly with matrix algebra routines such as this. 3458 See, e.g., `KSPCreate()`. 3459 3460 Fortran Note: 3461 A valid (non-null) `info` argument must be provided 3462 3463 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3464 @*/ 3465 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3466 { 3467 MatFactorInfo tinfo; 3468 3469 PetscFunctionBegin; 3470 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3471 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3472 PetscValidType(fact, 1); 3473 PetscValidType(mat, 2); 3474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3475 PetscCheck(mat->rmap->N == (fact)->rmap->N && mat->cmap->N == (fact)->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dim %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3476 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3477 MatCheckPreallocated(mat, 2); 3478 if (!info) { 3479 PetscCall(MatFactorInfoInitialize(&tinfo)); 3480 info = &tinfo; 3481 } 3482 3483 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3484 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3485 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3486 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3487 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3488 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3489 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3490 PetscFunctionReturn(PETSC_SUCCESS); 3491 } 3492 3493 /*@ 3494 MatQRFactor - Performs in-place QR factorization of matrix. 3495 3496 Collective 3497 3498 Input Parameters: 3499 + mat - the matrix 3500 . col - column permutation 3501 - info - options for factorization, includes 3502 .vb 3503 fill - expected fill as ratio of original fill. 3504 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3505 Run with the option -info to determine an optimal value to use 3506 .ve 3507 3508 Level: developer 3509 3510 Notes: 3511 Most users should employ the `KSP` interface for linear solvers 3512 instead of working directly with matrix algebra routines such as this. 3513 See, e.g., `KSPCreate()`. 3514 3515 This changes the state of the matrix to a factored matrix; it cannot be used 3516 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3517 3518 Fortran Note: 3519 A valid (non-null) `info` argument must be provided 3520 3521 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3522 `MatSetUnfactored()` 3523 @*/ 3524 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3525 { 3526 PetscFunctionBegin; 3527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3528 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3529 if (info) PetscAssertPointer(info, 3); 3530 PetscValidType(mat, 1); 3531 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3532 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3533 MatCheckPreallocated(mat, 1); 3534 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3535 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3536 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3537 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3538 PetscFunctionReturn(PETSC_SUCCESS); 3539 } 3540 3541 /*@ 3542 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3543 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3544 3545 Collective 3546 3547 Input Parameters: 3548 + fact - the factor matrix obtained with `MatGetFactor()` 3549 . mat - the matrix 3550 . col - column permutation 3551 - info - options for factorization, includes 3552 .vb 3553 fill - expected fill as ratio of original fill. 3554 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3555 Run with the option -info to determine an optimal value to use 3556 .ve 3557 3558 Level: developer 3559 3560 Note: 3561 Most users should employ the `KSP` interface for linear solvers 3562 instead of working directly with matrix algebra routines such as this. 3563 See, e.g., `KSPCreate()`. 3564 3565 Fortran Note: 3566 A valid (non-null) `info` argument must be provided 3567 3568 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3569 @*/ 3570 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3571 { 3572 MatFactorInfo tinfo; 3573 3574 PetscFunctionBegin; 3575 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3576 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3577 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3578 if (info) PetscAssertPointer(info, 4); 3579 PetscValidType(fact, 1); 3580 PetscValidType(mat, 2); 3581 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3582 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3583 MatCheckPreallocated(mat, 2); 3584 if (!info) { 3585 PetscCall(MatFactorInfoInitialize(&tinfo)); 3586 info = &tinfo; 3587 } 3588 3589 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3590 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3591 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3592 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3593 PetscFunctionReturn(PETSC_SUCCESS); 3594 } 3595 3596 /*@ 3597 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3598 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3599 3600 Collective 3601 3602 Input Parameters: 3603 + fact - the factor matrix obtained with `MatGetFactor()` 3604 . mat - the matrix 3605 - info - options for factorization 3606 3607 Level: developer 3608 3609 Notes: 3610 See `MatQRFactor()` for in-place factorization. 3611 3612 Most users should employ the `KSP` interface for linear solvers 3613 instead of working directly with matrix algebra routines such as this. 3614 See, e.g., `KSPCreate()`. 3615 3616 Fortran Note: 3617 A valid (non-null) `info` argument must be provided 3618 3619 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3620 @*/ 3621 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3622 { 3623 MatFactorInfo tinfo; 3624 3625 PetscFunctionBegin; 3626 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3627 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3628 PetscValidType(fact, 1); 3629 PetscValidType(mat, 2); 3630 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3631 PetscCheck(mat->rmap->N == fact->rmap->N && mat->cmap->N == fact->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Mat fact: global dimensions are different %" PetscInt_FMT " should = %" PetscInt_FMT " %" PetscInt_FMT " should = %" PetscInt_FMT, 3632 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3633 3634 MatCheckPreallocated(mat, 2); 3635 if (!info) { 3636 PetscCall(MatFactorInfoInitialize(&tinfo)); 3637 info = &tinfo; 3638 } 3639 3640 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3641 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3642 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3643 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3644 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3645 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3646 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3647 PetscFunctionReturn(PETSC_SUCCESS); 3648 } 3649 3650 /*@ 3651 MatSolve - Solves $A x = b$, given a factored matrix. 3652 3653 Neighbor-wise Collective 3654 3655 Input Parameters: 3656 + mat - the factored matrix 3657 - b - the right-hand-side vector 3658 3659 Output Parameter: 3660 . x - the result vector 3661 3662 Level: developer 3663 3664 Notes: 3665 The vectors `b` and `x` cannot be the same. I.e., one cannot 3666 call `MatSolve`(A,x,x). 3667 3668 Most users should employ the `KSP` interface for linear solvers 3669 instead of working directly with matrix algebra routines such as this. 3670 See, e.g., `KSPCreate()`. 3671 3672 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3673 @*/ 3674 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3675 { 3676 PetscFunctionBegin; 3677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3678 PetscValidType(mat, 1); 3679 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3680 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3681 PetscCheckSameComm(mat, 1, b, 2); 3682 PetscCheckSameComm(mat, 1, x, 3); 3683 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3684 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3685 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3686 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3687 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3688 MatCheckPreallocated(mat, 1); 3689 3690 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3691 PetscCall(VecFlag(x, mat->factorerrortype)); 3692 if (mat->factorerrortype) { 3693 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3694 } else PetscUseTypeMethod(mat, solve, b, x); 3695 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3696 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3697 PetscFunctionReturn(PETSC_SUCCESS); 3698 } 3699 3700 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3701 { 3702 Vec b, x; 3703 PetscInt N, i; 3704 PetscErrorCode (*f)(Mat, Vec, Vec); 3705 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3706 3707 PetscFunctionBegin; 3708 if (A->factorerrortype) { 3709 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3710 PetscCall(MatSetInf(X)); 3711 PetscFunctionReturn(PETSC_SUCCESS); 3712 } 3713 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3714 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3715 PetscCall(MatBoundToCPU(A, &Abound)); 3716 if (!Abound) { 3717 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3718 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3719 } 3720 #if PetscDefined(HAVE_CUDA) 3721 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3722 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3723 #elif PetscDefined(HAVE_HIP) 3724 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3725 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3726 #endif 3727 PetscCall(MatGetSize(B, NULL, &N)); 3728 for (i = 0; i < N; i++) { 3729 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3730 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3731 PetscCall((*f)(A, b, x)); 3732 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3733 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3734 } 3735 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3736 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3737 PetscFunctionReturn(PETSC_SUCCESS); 3738 } 3739 3740 /*@ 3741 MatMatSolve - Solves $A X = B$, given a factored matrix. 3742 3743 Neighbor-wise Collective 3744 3745 Input Parameters: 3746 + A - the factored matrix 3747 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3748 3749 Output Parameter: 3750 . X - the result matrix (dense matrix) 3751 3752 Level: developer 3753 3754 Note: 3755 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3756 otherwise, `B` and `X` cannot be the same. 3757 3758 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3759 @*/ 3760 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3761 { 3762 PetscFunctionBegin; 3763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3764 PetscValidType(A, 1); 3765 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3766 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3767 PetscCheckSameComm(A, 1, B, 2); 3768 PetscCheckSameComm(A, 1, X, 3); 3769 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3770 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3771 PetscCheck(X->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3772 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3773 MatCheckPreallocated(A, 1); 3774 3775 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3776 if (!A->ops->matsolve) { 3777 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3778 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3779 } else PetscUseTypeMethod(A, matsolve, B, X); 3780 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3781 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3782 PetscFunctionReturn(PETSC_SUCCESS); 3783 } 3784 3785 /*@ 3786 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3787 3788 Neighbor-wise Collective 3789 3790 Input Parameters: 3791 + A - the factored matrix 3792 - B - the right-hand-side matrix (`MATDENSE` matrix) 3793 3794 Output Parameter: 3795 . X - the result matrix (dense matrix) 3796 3797 Level: developer 3798 3799 Note: 3800 The matrices `B` and `X` cannot be the same. I.e., one cannot 3801 call `MatMatSolveTranspose`(A,X,X). 3802 3803 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3804 @*/ 3805 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3806 { 3807 PetscFunctionBegin; 3808 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3809 PetscValidType(A, 1); 3810 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3811 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3812 PetscCheckSameComm(A, 1, B, 2); 3813 PetscCheckSameComm(A, 1, X, 3); 3814 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3815 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3816 PetscCheck(A->rmap->N == B->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N); 3817 PetscCheck(A->rmap->n == B->rmap->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat A,Mat B: local dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->n, B->rmap->n); 3818 PetscCheck(X->cmap->N >= B->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as rhs matrix"); 3819 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3820 MatCheckPreallocated(A, 1); 3821 3822 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3823 if (!A->ops->matsolvetranspose) { 3824 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3825 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3826 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3827 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3828 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3829 PetscFunctionReturn(PETSC_SUCCESS); 3830 } 3831 3832 /*@ 3833 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3834 3835 Neighbor-wise Collective 3836 3837 Input Parameters: 3838 + A - the factored matrix 3839 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3840 3841 Output Parameter: 3842 . X - the result matrix (dense matrix) 3843 3844 Level: developer 3845 3846 Note: 3847 For MUMPS, it only supports centralized sparse compressed column format on the host processor for right-hand side matrix. User must create `Bt` in sparse compressed row 3848 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3849 3850 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3851 @*/ 3852 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3853 { 3854 PetscFunctionBegin; 3855 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3856 PetscValidType(A, 1); 3857 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3858 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3859 PetscCheckSameComm(A, 1, Bt, 2); 3860 PetscCheckSameComm(A, 1, X, 3); 3861 3862 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3863 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3864 PetscCheck(A->rmap->N == Bt->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat Bt: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, Bt->cmap->N); 3865 PetscCheck(X->cmap->N >= Bt->rmap->N, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_SIZ, "Solution matrix must have same number of columns as row number of the rhs matrix"); 3866 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3867 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3868 MatCheckPreallocated(A, 1); 3869 3870 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3871 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3872 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3873 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3874 PetscFunctionReturn(PETSC_SUCCESS); 3875 } 3876 3877 /*@ 3878 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3879 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3880 3881 Neighbor-wise Collective 3882 3883 Input Parameters: 3884 + mat - the factored matrix 3885 - b - the right-hand-side vector 3886 3887 Output Parameter: 3888 . x - the result vector 3889 3890 Level: developer 3891 3892 Notes: 3893 `MatSolve()` should be used for most applications, as it performs 3894 a forward solve followed by a backward solve. 3895 3896 The vectors `b` and `x` cannot be the same, i.e., one cannot 3897 call `MatForwardSolve`(A,x,x). 3898 3899 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3900 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3901 `MatForwardSolve()` solves $U^T*D y = b$, and 3902 `MatBackwardSolve()` solves $U x = y$. 3903 Thus they do not provide a symmetric preconditioner. 3904 3905 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3906 @*/ 3907 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3908 { 3909 PetscFunctionBegin; 3910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3911 PetscValidType(mat, 1); 3912 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3913 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3914 PetscCheckSameComm(mat, 1, b, 2); 3915 PetscCheckSameComm(mat, 1, x, 3); 3916 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3917 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3918 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3919 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3920 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3921 MatCheckPreallocated(mat, 1); 3922 3923 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3924 PetscUseTypeMethod(mat, forwardsolve, b, x); 3925 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3926 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3927 PetscFunctionReturn(PETSC_SUCCESS); 3928 } 3929 3930 /*@ 3931 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3932 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3933 3934 Neighbor-wise Collective 3935 3936 Input Parameters: 3937 + mat - the factored matrix 3938 - b - the right-hand-side vector 3939 3940 Output Parameter: 3941 . x - the result vector 3942 3943 Level: developer 3944 3945 Notes: 3946 `MatSolve()` should be used for most applications, as it performs 3947 a forward solve followed by a backward solve. 3948 3949 The vectors `b` and `x` cannot be the same. I.e., one cannot 3950 call `MatBackwardSolve`(A,x,x). 3951 3952 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3953 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3954 `MatForwardSolve()` solves $U^T*D y = b$, and 3955 `MatBackwardSolve()` solves $U x = y$. 3956 Thus they do not provide a symmetric preconditioner. 3957 3958 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3959 @*/ 3960 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3961 { 3962 PetscFunctionBegin; 3963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3964 PetscValidType(mat, 1); 3965 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3966 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3967 PetscCheckSameComm(mat, 1, b, 2); 3968 PetscCheckSameComm(mat, 1, x, 3); 3969 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3970 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 3971 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 3972 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 3973 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3974 MatCheckPreallocated(mat, 1); 3975 3976 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3977 PetscUseTypeMethod(mat, backwardsolve, b, x); 3978 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3979 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3980 PetscFunctionReturn(PETSC_SUCCESS); 3981 } 3982 3983 /*@ 3984 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3985 3986 Neighbor-wise Collective 3987 3988 Input Parameters: 3989 + mat - the factored matrix 3990 . b - the right-hand-side vector 3991 - y - the vector to be added to 3992 3993 Output Parameter: 3994 . x - the result vector 3995 3996 Level: developer 3997 3998 Note: 3999 The vectors `b` and `x` cannot be the same. I.e., one cannot 4000 call `MatSolveAdd`(A,x,y,x). 4001 4002 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4003 @*/ 4004 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4005 { 4006 PetscScalar one = 1.0; 4007 Vec tmp; 4008 4009 PetscFunctionBegin; 4010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4011 PetscValidType(mat, 1); 4012 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4013 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4014 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4015 PetscCheckSameComm(mat, 1, b, 2); 4016 PetscCheckSameComm(mat, 1, y, 3); 4017 PetscCheckSameComm(mat, 1, x, 4); 4018 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4019 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4020 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4021 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 4022 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4023 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4024 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4025 MatCheckPreallocated(mat, 1); 4026 4027 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4028 PetscCall(VecFlag(x, mat->factorerrortype)); 4029 if (mat->factorerrortype) { 4030 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4031 } else if (mat->ops->solveadd) { 4032 PetscUseTypeMethod(mat, solveadd, b, y, x); 4033 } else { 4034 /* do the solve then the add manually */ 4035 if (x != y) { 4036 PetscCall(MatSolve(mat, b, x)); 4037 PetscCall(VecAXPY(x, one, y)); 4038 } else { 4039 PetscCall(VecDuplicate(x, &tmp)); 4040 PetscCall(VecCopy(x, tmp)); 4041 PetscCall(MatSolve(mat, b, x)); 4042 PetscCall(VecAXPY(x, one, tmp)); 4043 PetscCall(VecDestroy(&tmp)); 4044 } 4045 } 4046 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4047 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4048 PetscFunctionReturn(PETSC_SUCCESS); 4049 } 4050 4051 /*@ 4052 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4053 4054 Neighbor-wise Collective 4055 4056 Input Parameters: 4057 + mat - the factored matrix 4058 - b - the right-hand-side vector 4059 4060 Output Parameter: 4061 . x - the result vector 4062 4063 Level: developer 4064 4065 Notes: 4066 The vectors `b` and `x` cannot be the same. I.e., one cannot 4067 call `MatSolveTranspose`(A,x,x). 4068 4069 Most users should employ the `KSP` interface for linear solvers 4070 instead of working directly with matrix algebra routines such as this. 4071 See, e.g., `KSPCreate()`. 4072 4073 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4074 @*/ 4075 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4076 { 4077 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4078 4079 PetscFunctionBegin; 4080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4081 PetscValidType(mat, 1); 4082 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4083 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4084 PetscCheckSameComm(mat, 1, b, 2); 4085 PetscCheckSameComm(mat, 1, x, 3); 4086 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4087 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4088 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4089 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4090 MatCheckPreallocated(mat, 1); 4091 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4092 PetscCall(VecFlag(x, mat->factorerrortype)); 4093 if (mat->factorerrortype) { 4094 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4095 } else { 4096 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4097 PetscCall((*f)(mat, b, x)); 4098 } 4099 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4100 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4101 PetscFunctionReturn(PETSC_SUCCESS); 4102 } 4103 4104 /*@ 4105 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4106 factored matrix. 4107 4108 Neighbor-wise Collective 4109 4110 Input Parameters: 4111 + mat - the factored matrix 4112 . b - the right-hand-side vector 4113 - y - the vector to be added to 4114 4115 Output Parameter: 4116 . x - the result vector 4117 4118 Level: developer 4119 4120 Note: 4121 The vectors `b` and `x` cannot be the same. I.e., one cannot 4122 call `MatSolveTransposeAdd`(A,x,y,x). 4123 4124 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4125 @*/ 4126 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4127 { 4128 PetscScalar one = 1.0; 4129 Vec tmp; 4130 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4131 4132 PetscFunctionBegin; 4133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4134 PetscValidType(mat, 1); 4135 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4136 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4137 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4138 PetscCheckSameComm(mat, 1, b, 2); 4139 PetscCheckSameComm(mat, 1, y, 3); 4140 PetscCheckSameComm(mat, 1, x, 4); 4141 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4142 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 4143 PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N); 4144 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 4145 PetscCheck(x->map->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Vec x,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, x->map->n, y->map->n); 4146 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4147 MatCheckPreallocated(mat, 1); 4148 4149 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4150 PetscCall(VecFlag(x, mat->factorerrortype)); 4151 if (mat->factorerrortype) { 4152 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4153 } else if (f) { 4154 PetscCall((*f)(mat, b, y, x)); 4155 } else { 4156 /* do the solve then the add manually */ 4157 if (x != y) { 4158 PetscCall(MatSolveTranspose(mat, b, x)); 4159 PetscCall(VecAXPY(x, one, y)); 4160 } else { 4161 PetscCall(VecDuplicate(x, &tmp)); 4162 PetscCall(VecCopy(x, tmp)); 4163 PetscCall(MatSolveTranspose(mat, b, x)); 4164 PetscCall(VecAXPY(x, one, tmp)); 4165 PetscCall(VecDestroy(&tmp)); 4166 } 4167 } 4168 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4169 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4170 PetscFunctionReturn(PETSC_SUCCESS); 4171 } 4172 4173 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4174 /*@ 4175 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4176 4177 Neighbor-wise Collective 4178 4179 Input Parameters: 4180 + mat - the matrix 4181 . b - the right-hand side 4182 . omega - the relaxation factor 4183 . flag - flag indicating the type of SOR (see below) 4184 . shift - diagonal shift 4185 . its - the number of iterations 4186 - lits - the number of local iterations 4187 4188 Output Parameter: 4189 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4190 4191 SOR Flags: 4192 + `SOR_FORWARD_SWEEP` - forward SOR 4193 . `SOR_BACKWARD_SWEEP` - backward SOR 4194 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4195 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4196 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4197 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4198 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4199 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4200 upper/lower triangular part of matrix to 4201 vector (with omega) 4202 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4203 4204 Level: developer 4205 4206 Notes: 4207 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4208 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4209 on each processor. 4210 4211 Application programmers will not generally use `MatSOR()` directly, 4212 but instead will employ the `KSP`/`PC` interface. 4213 4214 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4215 4216 Most users should employ the `KSP` interface for linear solvers 4217 instead of working directly with matrix algebra routines such as this. 4218 See, e.g., `KSPCreate()`. 4219 4220 Vectors `x` and `b` CANNOT be the same 4221 4222 The flags are implemented as bitwise inclusive or operations. 4223 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4224 to specify a zero initial guess for SSOR. 4225 4226 Developer Note: 4227 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4228 4229 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4230 @*/ 4231 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4232 { 4233 PetscFunctionBegin; 4234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4235 PetscValidType(mat, 1); 4236 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4237 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4238 PetscCheckSameComm(mat, 1, b, 2); 4239 PetscCheckSameComm(mat, 1, x, 8); 4240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4241 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4242 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 4243 PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N); 4244 PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n); 4245 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4246 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4247 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4248 4249 MatCheckPreallocated(mat, 1); 4250 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4251 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4252 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4253 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4254 PetscFunctionReturn(PETSC_SUCCESS); 4255 } 4256 4257 /* 4258 Default matrix copy routine. 4259 */ 4260 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4261 { 4262 PetscInt i, rstart = 0, rend = 0, nz; 4263 const PetscInt *cwork; 4264 const PetscScalar *vwork; 4265 4266 PetscFunctionBegin; 4267 if (B->assembled) PetscCall(MatZeroEntries(B)); 4268 if (str == SAME_NONZERO_PATTERN) { 4269 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4270 for (i = rstart; i < rend; i++) { 4271 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4272 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4273 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4274 } 4275 } else { 4276 PetscCall(MatAYPX(B, 0.0, A, str)); 4277 } 4278 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4279 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4280 PetscFunctionReturn(PETSC_SUCCESS); 4281 } 4282 4283 /*@ 4284 MatCopy - Copies a matrix to another matrix. 4285 4286 Collective 4287 4288 Input Parameters: 4289 + A - the matrix 4290 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4291 4292 Output Parameter: 4293 . B - where the copy is put 4294 4295 Level: intermediate 4296 4297 Notes: 4298 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4299 4300 `MatCopy()` copies the matrix entries of a matrix to another existing 4301 matrix (after first zeroing the second matrix). A related routine is 4302 `MatConvert()`, which first creates a new matrix and then copies the data. 4303 4304 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4305 @*/ 4306 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4307 { 4308 PetscInt i; 4309 4310 PetscFunctionBegin; 4311 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4312 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4313 PetscValidType(A, 1); 4314 PetscValidType(B, 2); 4315 PetscCheckSameComm(A, 1, B, 2); 4316 MatCheckPreallocated(B, 2); 4317 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4318 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4319 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim (%" PetscInt_FMT ",%" PetscInt_FMT ") (%" PetscInt_FMT ",%" PetscInt_FMT ")", A->rmap->N, B->rmap->N, 4320 A->cmap->N, B->cmap->N); 4321 MatCheckPreallocated(A, 1); 4322 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4323 4324 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4325 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4326 else PetscCall(MatCopy_Basic(A, B, str)); 4327 4328 B->stencil.dim = A->stencil.dim; 4329 B->stencil.noc = A->stencil.noc; 4330 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4331 B->stencil.dims[i] = A->stencil.dims[i]; 4332 B->stencil.starts[i] = A->stencil.starts[i]; 4333 } 4334 4335 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4336 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4337 PetscFunctionReturn(PETSC_SUCCESS); 4338 } 4339 4340 /*@ 4341 MatConvert - Converts a matrix to another matrix, either of the same 4342 or different type. 4343 4344 Collective 4345 4346 Input Parameters: 4347 + mat - the matrix 4348 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4349 same type as the original matrix. 4350 - reuse - denotes if the destination matrix is to be created or reused. 4351 Use `MAT_INPLACE_MATRIX` for inplace conversion (that is when you want the input `Mat` to be changed to contain the matrix in the new format), otherwise use 4352 `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` (can only be used after the first call was made with `MAT_INITIAL_MATRIX`, causes the matrix space in M to be reused). 4353 4354 Output Parameter: 4355 . M - pointer to place new matrix 4356 4357 Level: intermediate 4358 4359 Notes: 4360 `MatConvert()` first creates a new matrix and then copies the data from 4361 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4362 entries of one matrix to another already existing matrix context. 4363 4364 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4365 the MPI communicator of the generated matrix is always the same as the communicator 4366 of the input matrix. 4367 4368 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4369 @*/ 4370 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4371 { 4372 PetscBool sametype, issame, flg; 4373 PetscBool3 issymmetric, ishermitian; 4374 char convname[256], mtype[256]; 4375 Mat B; 4376 4377 PetscFunctionBegin; 4378 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4379 PetscValidType(mat, 1); 4380 PetscAssertPointer(M, 4); 4381 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4382 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4383 MatCheckPreallocated(mat, 1); 4384 4385 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4386 if (flg) newtype = mtype; 4387 4388 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4389 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4390 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4391 if (reuse == MAT_REUSE_MATRIX) { 4392 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4393 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4394 } 4395 4396 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4397 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4398 PetscFunctionReturn(PETSC_SUCCESS); 4399 } 4400 4401 /* Cache Mat options because some converters use MatHeaderReplace */ 4402 issymmetric = mat->symmetric; 4403 ishermitian = mat->hermitian; 4404 4405 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4406 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4407 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4408 } else { 4409 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4410 const char *prefix[3] = {"seq", "mpi", ""}; 4411 PetscInt i; 4412 /* 4413 Order of precedence: 4414 0) See if newtype is a superclass of the current matrix. 4415 1) See if a specialized converter is known to the current matrix. 4416 2) See if a specialized converter is known to the desired matrix class. 4417 3) See if a good general converter is registered for the desired class 4418 (as of 6/27/03 only MATMPIADJ falls into this category). 4419 4) See if a good general converter is known for the current matrix. 4420 5) Use a really basic converter. 4421 */ 4422 4423 /* 0) See if newtype is a superclass of the current matrix. 4424 i.e mat is mpiaij and newtype is aij */ 4425 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4426 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4427 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4428 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4429 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4430 if (flg) { 4431 if (reuse == MAT_INPLACE_MATRIX) { 4432 PetscCall(PetscInfo(mat, "Early return\n")); 4433 PetscFunctionReturn(PETSC_SUCCESS); 4434 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4435 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4436 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4437 PetscFunctionReturn(PETSC_SUCCESS); 4438 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4439 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4440 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4441 PetscFunctionReturn(PETSC_SUCCESS); 4442 } 4443 } 4444 } 4445 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4446 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4447 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4448 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4449 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4450 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4451 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4452 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4453 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4454 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4455 if (conv) goto foundconv; 4456 } 4457 4458 /* 2) See if a specialized converter is known to the desired matrix class. */ 4459 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4460 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4461 PetscCall(MatSetType(B, newtype)); 4462 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4463 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4464 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4465 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4466 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4467 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4468 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4469 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4470 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4471 if (conv) { 4472 PetscCall(MatDestroy(&B)); 4473 goto foundconv; 4474 } 4475 } 4476 4477 /* 3) See if a good general converter is registered for the desired class */ 4478 conv = B->ops->convertfrom; 4479 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4480 PetscCall(MatDestroy(&B)); 4481 if (conv) goto foundconv; 4482 4483 /* 4) See if a good general converter is known for the current matrix */ 4484 if (mat->ops->convert) conv = mat->ops->convert; 4485 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4486 if (conv) goto foundconv; 4487 4488 /* 5) Use a really basic converter. */ 4489 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4490 conv = MatConvert_Basic; 4491 4492 foundconv: 4493 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4494 PetscCall((*conv)(mat, newtype, reuse, M)); 4495 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4496 /* the block sizes must be same if the mappings are copied over */ 4497 (*M)->rmap->bs = mat->rmap->bs; 4498 (*M)->cmap->bs = mat->cmap->bs; 4499 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4500 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4501 (*M)->rmap->mapping = mat->rmap->mapping; 4502 (*M)->cmap->mapping = mat->cmap->mapping; 4503 } 4504 (*M)->stencil.dim = mat->stencil.dim; 4505 (*M)->stencil.noc = mat->stencil.noc; 4506 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4507 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4508 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4509 } 4510 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4511 } 4512 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4513 4514 /* Copy Mat options */ 4515 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4516 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4517 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4518 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4519 PetscFunctionReturn(PETSC_SUCCESS); 4520 } 4521 4522 /*@ 4523 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4524 4525 Not Collective 4526 4527 Input Parameter: 4528 . mat - the matrix, must be a factored matrix 4529 4530 Output Parameter: 4531 . type - the string name of the package (do not free this string) 4532 4533 Level: intermediate 4534 4535 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4536 @*/ 4537 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4538 { 4539 PetscErrorCode (*conv)(Mat, MatSolverType *); 4540 4541 PetscFunctionBegin; 4542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4543 PetscValidType(mat, 1); 4544 PetscAssertPointer(type, 2); 4545 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4546 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4547 if (conv) PetscCall((*conv)(mat, type)); 4548 else *type = MATSOLVERPETSC; 4549 PetscFunctionReturn(PETSC_SUCCESS); 4550 } 4551 4552 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4553 struct _MatSolverTypeForSpecifcType { 4554 MatType mtype; 4555 /* no entry for MAT_FACTOR_NONE */ 4556 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4557 MatSolverTypeForSpecifcType next; 4558 }; 4559 4560 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4561 struct _MatSolverTypeHolder { 4562 char *name; 4563 MatSolverTypeForSpecifcType handlers; 4564 MatSolverTypeHolder next; 4565 }; 4566 4567 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4568 4569 /*@C 4570 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4571 4572 Logically Collective, No Fortran Support 4573 4574 Input Parameters: 4575 + package - name of the package, for example `petsc` or `superlu` 4576 . mtype - the matrix type that works with this package 4577 . ftype - the type of factorization supported by the package 4578 - createfactor - routine that will create the factored matrix ready to be used 4579 4580 Level: developer 4581 4582 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4583 `MatGetFactor()` 4584 @*/ 4585 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4586 { 4587 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4588 PetscBool flg; 4589 MatSolverTypeForSpecifcType inext, iprev = NULL; 4590 4591 PetscFunctionBegin; 4592 PetscCall(MatInitializePackage()); 4593 if (!next) { 4594 PetscCall(PetscNew(&MatSolverTypeHolders)); 4595 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4596 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4597 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4598 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4599 PetscFunctionReturn(PETSC_SUCCESS); 4600 } 4601 while (next) { 4602 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4603 if (flg) { 4604 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4605 inext = next->handlers; 4606 while (inext) { 4607 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4608 if (flg) { 4609 inext->createfactor[(int)ftype - 1] = createfactor; 4610 PetscFunctionReturn(PETSC_SUCCESS); 4611 } 4612 iprev = inext; 4613 inext = inext->next; 4614 } 4615 PetscCall(PetscNew(&iprev->next)); 4616 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4617 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4618 PetscFunctionReturn(PETSC_SUCCESS); 4619 } 4620 prev = next; 4621 next = next->next; 4622 } 4623 PetscCall(PetscNew(&prev->next)); 4624 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4625 PetscCall(PetscNew(&prev->next->handlers)); 4626 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4627 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4628 PetscFunctionReturn(PETSC_SUCCESS); 4629 } 4630 4631 /*@C 4632 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4633 4634 Input Parameters: 4635 + type - name of the package, for example `petsc` or `superlu`, if this is 'NULL', then the first result that satisfies the other criteria is returned 4636 . ftype - the type of factorization supported by the type 4637 - mtype - the matrix type that works with this type 4638 4639 Output Parameters: 4640 + foundtype - `PETSC_TRUE` if the type was registered 4641 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4642 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4643 4644 Calling sequence of `createfactor`: 4645 + A - the matrix providing the factor matrix 4646 . ftype - the `MatFactorType` of the factor requested 4647 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4648 4649 Level: developer 4650 4651 Note: 4652 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4653 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4654 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4655 4656 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4657 `MatInitializePackage()` 4658 @*/ 4659 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4660 { 4661 MatSolverTypeHolder next = MatSolverTypeHolders; 4662 PetscBool flg; 4663 MatSolverTypeForSpecifcType inext; 4664 4665 PetscFunctionBegin; 4666 if (foundtype) *foundtype = PETSC_FALSE; 4667 if (foundmtype) *foundmtype = PETSC_FALSE; 4668 if (createfactor) *createfactor = NULL; 4669 4670 if (type) { 4671 while (next) { 4672 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4673 if (flg) { 4674 if (foundtype) *foundtype = PETSC_TRUE; 4675 inext = next->handlers; 4676 while (inext) { 4677 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4678 if (flg) { 4679 if (foundmtype) *foundmtype = PETSC_TRUE; 4680 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4681 PetscFunctionReturn(PETSC_SUCCESS); 4682 } 4683 inext = inext->next; 4684 } 4685 } 4686 next = next->next; 4687 } 4688 } else { 4689 while (next) { 4690 inext = next->handlers; 4691 while (inext) { 4692 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4693 if (flg && inext->createfactor[(int)ftype - 1]) { 4694 if (foundtype) *foundtype = PETSC_TRUE; 4695 if (foundmtype) *foundmtype = PETSC_TRUE; 4696 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4697 PetscFunctionReturn(PETSC_SUCCESS); 4698 } 4699 inext = inext->next; 4700 } 4701 next = next->next; 4702 } 4703 /* try with base classes inext->mtype */ 4704 next = MatSolverTypeHolders; 4705 while (next) { 4706 inext = next->handlers; 4707 while (inext) { 4708 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4709 if (flg && inext->createfactor[(int)ftype - 1]) { 4710 if (foundtype) *foundtype = PETSC_TRUE; 4711 if (foundmtype) *foundmtype = PETSC_TRUE; 4712 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4713 PetscFunctionReturn(PETSC_SUCCESS); 4714 } 4715 inext = inext->next; 4716 } 4717 next = next->next; 4718 } 4719 } 4720 PetscFunctionReturn(PETSC_SUCCESS); 4721 } 4722 4723 PetscErrorCode MatSolverTypeDestroy(void) 4724 { 4725 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4726 MatSolverTypeForSpecifcType inext, iprev; 4727 4728 PetscFunctionBegin; 4729 while (next) { 4730 PetscCall(PetscFree(next->name)); 4731 inext = next->handlers; 4732 while (inext) { 4733 PetscCall(PetscFree(inext->mtype)); 4734 iprev = inext; 4735 inext = inext->next; 4736 PetscCall(PetscFree(iprev)); 4737 } 4738 prev = next; 4739 next = next->next; 4740 PetscCall(PetscFree(prev)); 4741 } 4742 MatSolverTypeHolders = NULL; 4743 PetscFunctionReturn(PETSC_SUCCESS); 4744 } 4745 4746 /*@ 4747 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4748 4749 Logically Collective 4750 4751 Input Parameter: 4752 . mat - the matrix 4753 4754 Output Parameter: 4755 . flg - `PETSC_TRUE` if uses the ordering 4756 4757 Level: developer 4758 4759 Note: 4760 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4761 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4762 4763 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4764 @*/ 4765 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4766 { 4767 PetscFunctionBegin; 4768 *flg = mat->canuseordering; 4769 PetscFunctionReturn(PETSC_SUCCESS); 4770 } 4771 4772 /*@ 4773 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4774 4775 Logically Collective 4776 4777 Input Parameters: 4778 + mat - the matrix obtained with `MatGetFactor()` 4779 - ftype - the factorization type to be used 4780 4781 Output Parameter: 4782 . otype - the preferred ordering type 4783 4784 Level: developer 4785 4786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4787 @*/ 4788 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4789 { 4790 PetscFunctionBegin; 4791 *otype = mat->preferredordering[ftype]; 4792 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4793 PetscFunctionReturn(PETSC_SUCCESS); 4794 } 4795 4796 /*@ 4797 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4798 4799 Collective 4800 4801 Input Parameters: 4802 + mat - the matrix 4803 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's solver if it is available), if this is 'NULL', then the first result that satisfies 4804 the other criteria is returned 4805 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4806 4807 Output Parameter: 4808 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4809 4810 Options Database Keys: 4811 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4812 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4813 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4814 4815 Level: intermediate 4816 4817 Notes: 4818 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4819 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4820 4821 Users usually access the factorization solvers via `KSP` 4822 4823 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4824 such as pastix, superlu, mumps etc. PETSc must have been ./configure to use the external solver, using the option --download-package or --with-package-dir 4825 4826 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4827 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4828 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4829 4830 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4831 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4832 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4833 4834 Developer Note: 4835 This should actually be called `MatCreateFactor()` since it creates a new factor object 4836 4837 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4838 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4839 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4840 @*/ 4841 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4842 { 4843 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4844 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4845 4846 PetscFunctionBegin; 4847 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4848 PetscValidType(mat, 1); 4849 4850 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4851 MatCheckPreallocated(mat, 1); 4852 4853 PetscCall(MatIsShell(mat, &shell)); 4854 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4855 if (hasop) { 4856 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4857 PetscFunctionReturn(PETSC_SUCCESS); 4858 } 4859 4860 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4861 if (!foundtype) { 4862 if (type) { 4863 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate solver type %s for factorization type %s and matrix type %s. Perhaps you must ./configure with --download-%s", type, MatFactorTypes[ftype], 4864 ((PetscObject)mat)->type_name, type); 4865 } else { 4866 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "Could not locate a solver type for factorization type %s and matrix type %s.", MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4867 } 4868 } 4869 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4870 PetscCheck(conv, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support factorization type %s for matrix type %s", type, MatFactorTypes[ftype], ((PetscObject)mat)->type_name); 4871 4872 PetscCall((*conv)(mat, ftype, f)); 4873 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4874 PetscFunctionReturn(PETSC_SUCCESS); 4875 } 4876 4877 /*@ 4878 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4879 4880 Not Collective 4881 4882 Input Parameters: 4883 + mat - the matrix 4884 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4885 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4886 4887 Output Parameter: 4888 . flg - PETSC_TRUE if the factorization is available 4889 4890 Level: intermediate 4891 4892 Notes: 4893 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4894 such as pastix, superlu, mumps etc. 4895 4896 PETSc must have been ./configure to use the external solver, using the option --download-package 4897 4898 Developer Note: 4899 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4900 4901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4902 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4903 @*/ 4904 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4905 { 4906 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4907 4908 PetscFunctionBegin; 4909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4910 PetscAssertPointer(flg, 4); 4911 4912 *flg = PETSC_FALSE; 4913 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4914 4915 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4916 MatCheckPreallocated(mat, 1); 4917 4918 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4919 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4920 PetscFunctionReturn(PETSC_SUCCESS); 4921 } 4922 4923 /*@ 4924 MatDuplicate - Duplicates a matrix including the non-zero structure. 4925 4926 Collective 4927 4928 Input Parameters: 4929 + mat - the matrix 4930 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4931 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4932 4933 Output Parameter: 4934 . M - pointer to place new matrix 4935 4936 Level: intermediate 4937 4938 Notes: 4939 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4940 4941 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4942 4943 May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well. 4944 4945 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4946 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4947 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4948 4949 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4950 @*/ 4951 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4952 { 4953 Mat B; 4954 VecType vtype; 4955 PetscInt i; 4956 PetscObject dm, container_h, container_d; 4957 void (*viewf)(void); 4958 4959 PetscFunctionBegin; 4960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4961 PetscValidType(mat, 1); 4962 PetscAssertPointer(M, 3); 4963 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4964 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4965 MatCheckPreallocated(mat, 1); 4966 4967 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4968 PetscUseTypeMethod(mat, duplicate, op, M); 4969 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4970 B = *M; 4971 4972 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4973 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4974 PetscCall(MatGetVecType(mat, &vtype)); 4975 PetscCall(MatSetVecType(B, vtype)); 4976 4977 B->stencil.dim = mat->stencil.dim; 4978 B->stencil.noc = mat->stencil.noc; 4979 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4980 B->stencil.dims[i] = mat->stencil.dims[i]; 4981 B->stencil.starts[i] = mat->stencil.starts[i]; 4982 } 4983 4984 B->nooffproczerorows = mat->nooffproczerorows; 4985 B->nooffprocentries = mat->nooffprocentries; 4986 4987 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4988 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4989 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4990 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4991 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4992 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4993 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4994 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4995 PetscFunctionReturn(PETSC_SUCCESS); 4996 } 4997 4998 /*@ 4999 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5000 5001 Logically Collective 5002 5003 Input Parameter: 5004 . mat - the matrix 5005 5006 Output Parameter: 5007 . v - the diagonal of the matrix 5008 5009 Level: intermediate 5010 5011 Note: 5012 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5013 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5014 is larger than `ndiag`, the values of the remaining entries are unspecified. 5015 5016 Currently only correct in parallel for square matrices. 5017 5018 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5019 @*/ 5020 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5021 { 5022 PetscFunctionBegin; 5023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5024 PetscValidType(mat, 1); 5025 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5026 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5027 MatCheckPreallocated(mat, 1); 5028 if (PetscDefined(USE_DEBUG)) { 5029 PetscInt nv, row, col, ndiag; 5030 5031 PetscCall(VecGetLocalSize(v, &nv)); 5032 PetscCall(MatGetLocalSize(mat, &row, &col)); 5033 ndiag = PetscMin(row, col); 5034 PetscCheck(nv >= ndiag, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Nonconforming Mat and Vec. Vec local size %" PetscInt_FMT " < Mat local diagonal length %" PetscInt_FMT, nv, ndiag); 5035 } 5036 5037 PetscUseTypeMethod(mat, getdiagonal, v); 5038 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5039 PetscFunctionReturn(PETSC_SUCCESS); 5040 } 5041 5042 /*@ 5043 MatGetRowMin - Gets the minimum value (of the real part) of each 5044 row of the matrix 5045 5046 Logically Collective 5047 5048 Input Parameter: 5049 . mat - the matrix 5050 5051 Output Parameters: 5052 + v - the vector for storing the maximums 5053 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5054 5055 Level: intermediate 5056 5057 Note: 5058 The result of this call are the same as if one converted the matrix to dense format 5059 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5060 5061 This code is only implemented for a couple of matrix formats. 5062 5063 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5064 `MatGetRowMax()` 5065 @*/ 5066 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5067 { 5068 PetscFunctionBegin; 5069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5070 PetscValidType(mat, 1); 5071 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5072 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5073 5074 if (!mat->cmap->N) { 5075 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5076 if (idx) { 5077 PetscInt i, m = mat->rmap->n; 5078 for (i = 0; i < m; i++) idx[i] = -1; 5079 } 5080 } else { 5081 MatCheckPreallocated(mat, 1); 5082 } 5083 PetscUseTypeMethod(mat, getrowmin, v, idx); 5084 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5085 PetscFunctionReturn(PETSC_SUCCESS); 5086 } 5087 5088 /*@ 5089 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5090 row of the matrix 5091 5092 Logically Collective 5093 5094 Input Parameter: 5095 . mat - the matrix 5096 5097 Output Parameters: 5098 + v - the vector for storing the minimums 5099 - idx - the indices of the column found for each row (or `NULL` if not needed) 5100 5101 Level: intermediate 5102 5103 Notes: 5104 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5105 row is 0 (the first column). 5106 5107 This code is only implemented for a couple of matrix formats. 5108 5109 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5110 @*/ 5111 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5112 { 5113 PetscFunctionBegin; 5114 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5115 PetscValidType(mat, 1); 5116 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5117 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5118 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5119 5120 if (!mat->cmap->N) { 5121 PetscCall(VecSet(v, 0.0)); 5122 if (idx) { 5123 PetscInt i, m = mat->rmap->n; 5124 for (i = 0; i < m; i++) idx[i] = -1; 5125 } 5126 } else { 5127 MatCheckPreallocated(mat, 1); 5128 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5129 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5130 } 5131 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5132 PetscFunctionReturn(PETSC_SUCCESS); 5133 } 5134 5135 /*@ 5136 MatGetRowMax - Gets the maximum value (of the real part) of each 5137 row of the matrix 5138 5139 Logically Collective 5140 5141 Input Parameter: 5142 . mat - the matrix 5143 5144 Output Parameters: 5145 + v - the vector for storing the maximums 5146 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5147 5148 Level: intermediate 5149 5150 Notes: 5151 The result of this call are the same as if one converted the matrix to dense format 5152 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5153 5154 This code is only implemented for a couple of matrix formats. 5155 5156 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5157 @*/ 5158 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5159 { 5160 PetscFunctionBegin; 5161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5162 PetscValidType(mat, 1); 5163 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5164 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5165 5166 if (!mat->cmap->N) { 5167 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5168 if (idx) { 5169 PetscInt i, m = mat->rmap->n; 5170 for (i = 0; i < m; i++) idx[i] = -1; 5171 } 5172 } else { 5173 MatCheckPreallocated(mat, 1); 5174 PetscUseTypeMethod(mat, getrowmax, v, idx); 5175 } 5176 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5177 PetscFunctionReturn(PETSC_SUCCESS); 5178 } 5179 5180 /*@ 5181 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5182 row of the matrix 5183 5184 Logically Collective 5185 5186 Input Parameter: 5187 . mat - the matrix 5188 5189 Output Parameters: 5190 + v - the vector for storing the maximums 5191 - idx - the indices of the column found for each row (or `NULL` if not needed) 5192 5193 Level: intermediate 5194 5195 Notes: 5196 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5197 row is 0 (the first column). 5198 5199 This code is only implemented for a couple of matrix formats. 5200 5201 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5202 @*/ 5203 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5204 { 5205 PetscFunctionBegin; 5206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5207 PetscValidType(mat, 1); 5208 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5209 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5210 5211 if (!mat->cmap->N) { 5212 PetscCall(VecSet(v, 0.0)); 5213 if (idx) { 5214 PetscInt i, m = mat->rmap->n; 5215 for (i = 0; i < m; i++) idx[i] = -1; 5216 } 5217 } else { 5218 MatCheckPreallocated(mat, 1); 5219 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5220 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5221 } 5222 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5223 PetscFunctionReturn(PETSC_SUCCESS); 5224 } 5225 5226 /*@ 5227 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5228 5229 Logically Collective 5230 5231 Input Parameter: 5232 . mat - the matrix 5233 5234 Output Parameter: 5235 . v - the vector for storing the sum 5236 5237 Level: intermediate 5238 5239 This code is only implemented for a couple of matrix formats. 5240 5241 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5242 @*/ 5243 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5244 { 5245 PetscFunctionBegin; 5246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5247 PetscValidType(mat, 1); 5248 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5249 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5250 5251 if (!mat->cmap->N) { 5252 PetscCall(VecSet(v, 0.0)); 5253 } else { 5254 MatCheckPreallocated(mat, 1); 5255 PetscUseTypeMethod(mat, getrowsumabs, v); 5256 } 5257 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5258 PetscFunctionReturn(PETSC_SUCCESS); 5259 } 5260 5261 /*@ 5262 MatGetRowSum - Gets the sum of each row of the matrix 5263 5264 Logically or Neighborhood Collective 5265 5266 Input Parameter: 5267 . mat - the matrix 5268 5269 Output Parameter: 5270 . v - the vector for storing the sum of rows 5271 5272 Level: intermediate 5273 5274 Note: 5275 This code is slow since it is not currently specialized for different formats 5276 5277 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5278 @*/ 5279 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5280 { 5281 Vec ones; 5282 5283 PetscFunctionBegin; 5284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5285 PetscValidType(mat, 1); 5286 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5288 MatCheckPreallocated(mat, 1); 5289 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5290 PetscCall(VecSet(ones, 1.)); 5291 PetscCall(MatMult(mat, ones, v)); 5292 PetscCall(VecDestroy(&ones)); 5293 PetscFunctionReturn(PETSC_SUCCESS); 5294 } 5295 5296 /*@ 5297 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5298 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5299 5300 Collective 5301 5302 Input Parameter: 5303 . mat - the matrix to provide the transpose 5304 5305 Output Parameter: 5306 . B - the matrix to contain the transpose; it MUST have the nonzero structure of the transpose of A or the code will crash or generate incorrect results 5307 5308 Level: advanced 5309 5310 Note: 5311 Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This 5312 routine allows bypassing that call. 5313 5314 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5315 @*/ 5316 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5317 { 5318 MatParentState *rb = NULL; 5319 5320 PetscFunctionBegin; 5321 PetscCall(PetscNew(&rb)); 5322 rb->id = ((PetscObject)mat)->id; 5323 rb->state = 0; 5324 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5325 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5326 PetscFunctionReturn(PETSC_SUCCESS); 5327 } 5328 5329 /*@ 5330 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5331 5332 Collective 5333 5334 Input Parameters: 5335 + mat - the matrix to transpose 5336 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5337 5338 Output Parameter: 5339 . B - the transpose of the matrix 5340 5341 Level: intermediate 5342 5343 Notes: 5344 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5345 5346 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the 5347 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5348 5349 If the nonzero structure of `mat` changed from the previous call to this function with the same matrices an error will be generated for some matrix types. 5350 5351 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5352 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5353 5354 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5355 5356 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5357 5358 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5359 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5360 @*/ 5361 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5362 { 5363 PetscContainer rB = NULL; 5364 MatParentState *rb = NULL; 5365 5366 PetscFunctionBegin; 5367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5368 PetscValidType(mat, 1); 5369 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5370 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5371 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5372 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5373 MatCheckPreallocated(mat, 1); 5374 if (reuse == MAT_REUSE_MATRIX) { 5375 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5376 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5377 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5378 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5379 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5380 } 5381 5382 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5383 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5384 PetscUseTypeMethod(mat, transpose, reuse, B); 5385 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5386 } 5387 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5388 5389 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5390 if (reuse != MAT_INPLACE_MATRIX) { 5391 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5392 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5393 rb->state = ((PetscObject)mat)->state; 5394 rb->nonzerostate = mat->nonzerostate; 5395 } 5396 PetscFunctionReturn(PETSC_SUCCESS); 5397 } 5398 5399 /*@ 5400 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5401 5402 Collective 5403 5404 Input Parameter: 5405 . A - the matrix to transpose 5406 5407 Output Parameter: 5408 . B - the transpose. This is a complete matrix but the numerical portion is invalid. One can call `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) to compute the 5409 numerical portion. 5410 5411 Level: intermediate 5412 5413 Note: 5414 This is not supported for many matrix types, use `MatTranspose()` in those cases 5415 5416 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5417 @*/ 5418 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5419 { 5420 PetscFunctionBegin; 5421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5422 PetscValidType(A, 1); 5423 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5424 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5425 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5426 PetscUseTypeMethod(A, transposesymbolic, B); 5427 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5428 5429 PetscCall(MatTransposeSetPrecursor(A, *B)); 5430 PetscFunctionReturn(PETSC_SUCCESS); 5431 } 5432 5433 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5434 { 5435 PetscContainer rB; 5436 MatParentState *rb; 5437 5438 PetscFunctionBegin; 5439 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5440 PetscValidType(A, 1); 5441 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5442 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5443 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5444 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5445 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5446 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5447 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5448 PetscFunctionReturn(PETSC_SUCCESS); 5449 } 5450 5451 /*@ 5452 MatIsTranspose - Test whether a matrix is another one's transpose, 5453 or its own, in which case it tests symmetry. 5454 5455 Collective 5456 5457 Input Parameters: 5458 + A - the matrix to test 5459 . B - the matrix to test against, this can equal the first parameter 5460 - tol - tolerance, differences between entries smaller than this are counted as zero 5461 5462 Output Parameter: 5463 . flg - the result 5464 5465 Level: intermediate 5466 5467 Notes: 5468 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5469 test involves parallel copies of the block off-diagonal parts of the matrix. 5470 5471 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5472 @*/ 5473 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5474 { 5475 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5476 5477 PetscFunctionBegin; 5478 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5479 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5480 PetscAssertPointer(flg, 4); 5481 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5482 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5483 *flg = PETSC_FALSE; 5484 if (f && g) { 5485 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5486 PetscCall((*f)(A, B, tol, flg)); 5487 } else { 5488 MatType mattype; 5489 5490 PetscCall(MatGetType(f ? B : A, &mattype)); 5491 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5492 } 5493 PetscFunctionReturn(PETSC_SUCCESS); 5494 } 5495 5496 /*@ 5497 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5498 5499 Collective 5500 5501 Input Parameters: 5502 + mat - the matrix to transpose and complex conjugate 5503 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5504 5505 Output Parameter: 5506 . B - the Hermitian transpose 5507 5508 Level: intermediate 5509 5510 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5511 @*/ 5512 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5513 { 5514 PetscFunctionBegin; 5515 PetscCall(MatTranspose(mat, reuse, B)); 5516 #if defined(PETSC_USE_COMPLEX) 5517 PetscCall(MatConjugate(*B)); 5518 #endif 5519 PetscFunctionReturn(PETSC_SUCCESS); 5520 } 5521 5522 /*@ 5523 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5524 5525 Collective 5526 5527 Input Parameters: 5528 + A - the matrix to test 5529 . B - the matrix to test against, this can equal the first parameter 5530 - tol - tolerance, differences between entries smaller than this are counted as zero 5531 5532 Output Parameter: 5533 . flg - the result 5534 5535 Level: intermediate 5536 5537 Notes: 5538 Only available for `MATAIJ` matrices. 5539 5540 The sequential algorithm 5541 has a running time of the order of the number of nonzeros; the parallel 5542 test involves parallel copies of the block off-diagonal parts of the matrix. 5543 5544 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5545 @*/ 5546 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5547 { 5548 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5549 5550 PetscFunctionBegin; 5551 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5552 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5553 PetscAssertPointer(flg, 4); 5554 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5555 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5556 if (f && g) { 5557 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5558 PetscCall((*f)(A, B, tol, flg)); 5559 } 5560 PetscFunctionReturn(PETSC_SUCCESS); 5561 } 5562 5563 /*@ 5564 MatPermute - Creates a new matrix with rows and columns permuted from the 5565 original. 5566 5567 Collective 5568 5569 Input Parameters: 5570 + mat - the matrix to permute 5571 . row - row permutation, each processor supplies only the permutation for its rows 5572 - col - column permutation, each processor supplies only the permutation for its columns 5573 5574 Output Parameter: 5575 . B - the permuted matrix 5576 5577 Level: advanced 5578 5579 Note: 5580 The index sets map from row/col of permuted matrix to row/col of original matrix. 5581 The index sets should be on the same communicator as mat and have the same local sizes. 5582 5583 Developer Note: 5584 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5585 exploit the fact that row and col are permutations, consider implementing the 5586 more general `MatCreateSubMatrix()` instead. 5587 5588 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5589 @*/ 5590 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5591 { 5592 PetscFunctionBegin; 5593 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5594 PetscValidType(mat, 1); 5595 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5596 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5597 PetscAssertPointer(B, 4); 5598 PetscCheckSameComm(mat, 1, row, 2); 5599 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5601 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5602 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5603 MatCheckPreallocated(mat, 1); 5604 5605 if (mat->ops->permute) { 5606 PetscUseTypeMethod(mat, permute, row, col, B); 5607 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5608 } else { 5609 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5610 } 5611 PetscFunctionReturn(PETSC_SUCCESS); 5612 } 5613 5614 /*@ 5615 MatEqual - Compares two matrices. 5616 5617 Collective 5618 5619 Input Parameters: 5620 + A - the first matrix 5621 - B - the second matrix 5622 5623 Output Parameter: 5624 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5625 5626 Level: intermediate 5627 5628 Note: 5629 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product 5630 using several randomly created vectors, see `MatMultEqual()`. 5631 5632 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5633 @*/ 5634 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5635 { 5636 PetscFunctionBegin; 5637 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5638 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5639 PetscValidType(A, 1); 5640 PetscValidType(B, 2); 5641 PetscAssertPointer(flg, 3); 5642 PetscCheckSameComm(A, 1, B, 2); 5643 MatCheckPreallocated(A, 1); 5644 MatCheckPreallocated(B, 2); 5645 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5646 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5647 PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N, 5648 B->cmap->N); 5649 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5650 PetscUseTypeMethod(A, equal, B, flg); 5651 } else { 5652 PetscCall(MatMultEqual(A, B, 10, flg)); 5653 } 5654 PetscFunctionReturn(PETSC_SUCCESS); 5655 } 5656 5657 /*@ 5658 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5659 matrices that are stored as vectors. Either of the two scaling 5660 matrices can be `NULL`. 5661 5662 Collective 5663 5664 Input Parameters: 5665 + mat - the matrix to be scaled 5666 . l - the left scaling vector (or `NULL`) 5667 - r - the right scaling vector (or `NULL`) 5668 5669 Level: intermediate 5670 5671 Note: 5672 `MatDiagonalScale()` computes $A = LAR$, where 5673 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5674 The L scales the rows of the matrix, the R scales the columns of the matrix. 5675 5676 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5677 @*/ 5678 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5679 { 5680 PetscFunctionBegin; 5681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5682 PetscValidType(mat, 1); 5683 if (l) { 5684 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5685 PetscCheckSameComm(mat, 1, l, 2); 5686 } 5687 if (r) { 5688 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5689 PetscCheckSameComm(mat, 1, r, 3); 5690 } 5691 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5692 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5693 MatCheckPreallocated(mat, 1); 5694 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5695 5696 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5697 PetscUseTypeMethod(mat, diagonalscale, l, r); 5698 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5699 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5700 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5701 PetscFunctionReturn(PETSC_SUCCESS); 5702 } 5703 5704 /*@ 5705 MatScale - Scales all elements of a matrix by a given number. 5706 5707 Logically Collective 5708 5709 Input Parameters: 5710 + mat - the matrix to be scaled 5711 - a - the scaling value 5712 5713 Level: intermediate 5714 5715 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5716 @*/ 5717 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5718 { 5719 PetscFunctionBegin; 5720 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5721 PetscValidType(mat, 1); 5722 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5723 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5724 PetscValidLogicalCollectiveScalar(mat, a, 2); 5725 MatCheckPreallocated(mat, 1); 5726 5727 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5728 if (a != (PetscScalar)1.0) { 5729 PetscUseTypeMethod(mat, scale, a); 5730 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5731 } 5732 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5733 PetscFunctionReturn(PETSC_SUCCESS); 5734 } 5735 5736 /*@ 5737 MatNorm - Calculates various norms of a matrix. 5738 5739 Collective 5740 5741 Input Parameters: 5742 + mat - the matrix 5743 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5744 5745 Output Parameter: 5746 . nrm - the resulting norm 5747 5748 Level: intermediate 5749 5750 .seealso: [](ch_matrices), `Mat` 5751 @*/ 5752 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5753 { 5754 PetscFunctionBegin; 5755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5756 PetscValidType(mat, 1); 5757 PetscAssertPointer(nrm, 3); 5758 5759 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5760 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5761 MatCheckPreallocated(mat, 1); 5762 5763 PetscUseTypeMethod(mat, norm, type, nrm); 5764 PetscFunctionReturn(PETSC_SUCCESS); 5765 } 5766 5767 /* 5768 This variable is used to prevent counting of MatAssemblyBegin() that 5769 are called from within a MatAssemblyEnd(). 5770 */ 5771 static PetscInt MatAssemblyEnd_InUse = 0; 5772 /*@ 5773 MatAssemblyBegin - Begins assembling the matrix. This routine should 5774 be called after completing all calls to `MatSetValues()`. 5775 5776 Collective 5777 5778 Input Parameters: 5779 + mat - the matrix 5780 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5781 5782 Level: beginner 5783 5784 Notes: 5785 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5786 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5787 5788 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5789 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5790 using the matrix. 5791 5792 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5793 same flag of `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` for all processes. Thus you CANNOT locally change from `ADD_VALUES` to `INSERT_VALUES`, that is 5794 a global collective operation requiring all processes that share the matrix. 5795 5796 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5797 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5798 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5799 5800 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5801 @*/ 5802 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5803 { 5804 PetscFunctionBegin; 5805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5806 PetscValidType(mat, 1); 5807 MatCheckPreallocated(mat, 1); 5808 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5809 if (mat->assembled) { 5810 mat->was_assembled = PETSC_TRUE; 5811 mat->assembled = PETSC_FALSE; 5812 } 5813 5814 if (!MatAssemblyEnd_InUse) { 5815 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5816 PetscTryTypeMethod(mat, assemblybegin, type); 5817 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5818 } else PetscTryTypeMethod(mat, assemblybegin, type); 5819 PetscFunctionReturn(PETSC_SUCCESS); 5820 } 5821 5822 /*@ 5823 MatAssembled - Indicates if a matrix has been assembled and is ready for 5824 use; for example, in matrix-vector product. 5825 5826 Not Collective 5827 5828 Input Parameter: 5829 . mat - the matrix 5830 5831 Output Parameter: 5832 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5833 5834 Level: advanced 5835 5836 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5837 @*/ 5838 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5839 { 5840 PetscFunctionBegin; 5841 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5842 PetscAssertPointer(assembled, 2); 5843 *assembled = mat->assembled; 5844 PetscFunctionReturn(PETSC_SUCCESS); 5845 } 5846 5847 /*@ 5848 MatAssemblyEnd - Completes assembling the matrix. This routine should 5849 be called after `MatAssemblyBegin()`. 5850 5851 Collective 5852 5853 Input Parameters: 5854 + mat - the matrix 5855 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5856 5857 Options Database Keys: 5858 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5859 . -mat_view ::ascii_info_detail - Prints more detailed info 5860 . -mat_view - Prints matrix in ASCII format 5861 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5862 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5863 . -display <name> - Sets display name (default is host) 5864 . -draw_pause <sec> - Sets number of seconds to pause after display 5865 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5866 . -viewer_socket_machine <machine> - Machine to use for socket 5867 . -viewer_socket_port <port> - Port number to use for socket 5868 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5869 5870 Level: beginner 5871 5872 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5873 @*/ 5874 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5875 { 5876 static PetscInt inassm = 0; 5877 PetscBool flg = PETSC_FALSE; 5878 5879 PetscFunctionBegin; 5880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5881 PetscValidType(mat, 1); 5882 5883 inassm++; 5884 MatAssemblyEnd_InUse++; 5885 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5886 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5887 PetscTryTypeMethod(mat, assemblyend, type); 5888 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5889 } else PetscTryTypeMethod(mat, assemblyend, type); 5890 5891 /* Flush assembly is not a true assembly */ 5892 if (type != MAT_FLUSH_ASSEMBLY) { 5893 if (mat->num_ass) { 5894 if (!mat->symmetry_eternal) { 5895 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5896 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5897 } 5898 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5899 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5900 } 5901 mat->num_ass++; 5902 mat->assembled = PETSC_TRUE; 5903 mat->ass_nonzerostate = mat->nonzerostate; 5904 } 5905 5906 mat->insertmode = NOT_SET_VALUES; 5907 MatAssemblyEnd_InUse--; 5908 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5909 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5910 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5911 5912 if (mat->checksymmetryonassembly) { 5913 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5914 if (flg) { 5915 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5916 } else { 5917 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5918 } 5919 } 5920 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5921 } 5922 inassm--; 5923 PetscFunctionReturn(PETSC_SUCCESS); 5924 } 5925 5926 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5927 /*@ 5928 MatSetOption - Sets a parameter option for a matrix. Some options 5929 may be specific to certain storage formats. Some options 5930 determine how values will be inserted (or added). Sorted, 5931 row-oriented input will generally assemble the fastest. The default 5932 is row-oriented. 5933 5934 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5935 5936 Input Parameters: 5937 + mat - the matrix 5938 . op - the option, one of those listed below (and possibly others), 5939 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5940 5941 Options Describing Matrix Structure: 5942 + `MAT_SPD` - symmetric positive definite 5943 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5944 . `MAT_HERMITIAN` - transpose is the complex conjugation 5945 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5946 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5947 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5948 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5949 5950 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5951 do not need to be computed (usually at a high cost) 5952 5953 Options For Use with `MatSetValues()`: 5954 Insert a logically dense subblock, which can be 5955 . `MAT_ROW_ORIENTED` - row-oriented (default) 5956 5957 These options reflect the data you pass in with `MatSetValues()`; it has 5958 nothing to do with how the data is stored internally in the matrix 5959 data structure. 5960 5961 When (re)assembling a matrix, we can restrict the input for 5962 efficiency/debugging purposes. These options include 5963 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5964 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5965 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5966 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5967 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5968 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5969 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5970 performance for very large process counts. 5971 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5972 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5973 functions, instead sending only neighbor messages. 5974 5975 Level: intermediate 5976 5977 Notes: 5978 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5979 5980 Some options are relevant only for particular matrix types and 5981 are thus ignored by others. Other options are not supported by 5982 certain matrix types and will generate an error message if set. 5983 5984 If using Fortran to compute a matrix, one may need to 5985 use the column-oriented option (or convert to the row-oriented 5986 format). 5987 5988 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5989 that would generate a new entry in the nonzero structure is instead 5990 ignored. Thus, if memory has not already been allocated for this particular 5991 data, then the insertion is ignored. For dense matrices, in which 5992 the entire array is allocated, no entries are ever ignored. 5993 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5994 5995 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5996 that would generate a new entry in the nonzero structure instead produces 5997 an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats only.) If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5998 5999 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6000 that would generate a new entry that has not been preallocated will 6001 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6002 only.) This is a useful flag when debugging matrix memory preallocation. 6003 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6004 6005 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6006 other processors should be dropped, rather than stashed. 6007 This is useful if you know that the "owning" processor is also 6008 always generating the correct matrix entries, so that PETSc need 6009 not transfer duplicate entries generated on another processor. 6010 6011 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6012 searches during matrix assembly. When this flag is set, the hash table 6013 is created during the first matrix assembly. This hash table is 6014 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6015 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6016 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6017 supported by `MATMPIBAIJ` format only. 6018 6019 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6020 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6021 6022 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6023 a zero location in the matrix 6024 6025 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6026 6027 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6028 zero row routines and thus improves performance for very large process counts. 6029 6030 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6031 part of the matrix (since they should match the upper triangular part). 6032 6033 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6034 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6035 with finite difference schemes with non-periodic boundary conditions. 6036 6037 Developer Note: 6038 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6039 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6040 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6041 not changed. 6042 6043 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6044 @*/ 6045 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6046 { 6047 PetscFunctionBegin; 6048 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6049 if (op > 0) { 6050 PetscValidLogicalCollectiveEnum(mat, op, 2); 6051 PetscValidLogicalCollectiveBool(mat, flg, 3); 6052 } 6053 6054 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 6055 6056 switch (op) { 6057 case MAT_FORCE_DIAGONAL_ENTRIES: 6058 mat->force_diagonals = flg; 6059 PetscFunctionReturn(PETSC_SUCCESS); 6060 case MAT_NO_OFF_PROC_ENTRIES: 6061 mat->nooffprocentries = flg; 6062 PetscFunctionReturn(PETSC_SUCCESS); 6063 case MAT_SUBSET_OFF_PROC_ENTRIES: 6064 mat->assembly_subset = flg; 6065 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6066 #if !defined(PETSC_HAVE_MPIUNI) 6067 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6068 #endif 6069 mat->stash.first_assembly_done = PETSC_FALSE; 6070 } 6071 PetscFunctionReturn(PETSC_SUCCESS); 6072 case MAT_NO_OFF_PROC_ZERO_ROWS: 6073 mat->nooffproczerorows = flg; 6074 PetscFunctionReturn(PETSC_SUCCESS); 6075 case MAT_SPD: 6076 if (flg) { 6077 mat->spd = PETSC_BOOL3_TRUE; 6078 mat->symmetric = PETSC_BOOL3_TRUE; 6079 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6080 } else { 6081 mat->spd = PETSC_BOOL3_FALSE; 6082 } 6083 break; 6084 case MAT_SYMMETRIC: 6085 mat->symmetric = PetscBoolToBool3(flg); 6086 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6087 #if !defined(PETSC_USE_COMPLEX) 6088 mat->hermitian = PetscBoolToBool3(flg); 6089 #endif 6090 break; 6091 case MAT_HERMITIAN: 6092 mat->hermitian = PetscBoolToBool3(flg); 6093 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6094 #if !defined(PETSC_USE_COMPLEX) 6095 mat->symmetric = PetscBoolToBool3(flg); 6096 #endif 6097 break; 6098 case MAT_STRUCTURALLY_SYMMETRIC: 6099 mat->structurally_symmetric = PetscBoolToBool3(flg); 6100 break; 6101 case MAT_SYMMETRY_ETERNAL: 6102 PetscCheck(mat->symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SYMMETRY_ETERNAL without first setting MAT_SYMMETRIC to true or false"); 6103 mat->symmetry_eternal = flg; 6104 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6105 break; 6106 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6107 PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURALLY_SYMMETRIC to true or false"); 6108 mat->structural_symmetry_eternal = flg; 6109 break; 6110 case MAT_SPD_ETERNAL: 6111 PetscCheck(mat->spd != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_SPD_ETERNAL without first setting MAT_SPD to true or false"); 6112 mat->spd_eternal = flg; 6113 if (flg) { 6114 mat->structural_symmetry_eternal = PETSC_TRUE; 6115 mat->symmetry_eternal = PETSC_TRUE; 6116 } 6117 break; 6118 case MAT_STRUCTURE_ONLY: 6119 mat->structure_only = flg; 6120 break; 6121 case MAT_SORTED_FULL: 6122 mat->sortedfull = flg; 6123 break; 6124 default: 6125 break; 6126 } 6127 PetscTryTypeMethod(mat, setoption, op, flg); 6128 PetscFunctionReturn(PETSC_SUCCESS); 6129 } 6130 6131 /*@ 6132 MatGetOption - Gets a parameter option that has been set for a matrix. 6133 6134 Logically Collective 6135 6136 Input Parameters: 6137 + mat - the matrix 6138 - op - the option, this only responds to certain options, check the code for which ones 6139 6140 Output Parameter: 6141 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6142 6143 Level: intermediate 6144 6145 Notes: 6146 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6147 6148 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6149 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6150 6151 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6152 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6153 @*/ 6154 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6155 { 6156 PetscFunctionBegin; 6157 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6158 PetscValidType(mat, 1); 6159 6160 PetscCheck(((int)op) > MAT_OPTION_MIN && ((int)op) < MAT_OPTION_MAX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Options %d is out of range", (int)op); 6161 PetscCheck(((PetscObject)mat)->type_name, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_TYPENOTSET, "Cannot get options until type and size have been set, see MatSetType() and MatSetSizes()"); 6162 6163 switch (op) { 6164 case MAT_NO_OFF_PROC_ENTRIES: 6165 *flg = mat->nooffprocentries; 6166 break; 6167 case MAT_NO_OFF_PROC_ZERO_ROWS: 6168 *flg = mat->nooffproczerorows; 6169 break; 6170 case MAT_SYMMETRIC: 6171 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6172 break; 6173 case MAT_HERMITIAN: 6174 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6175 break; 6176 case MAT_STRUCTURALLY_SYMMETRIC: 6177 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6178 break; 6179 case MAT_SPD: 6180 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6181 break; 6182 case MAT_SYMMETRY_ETERNAL: 6183 *flg = mat->symmetry_eternal; 6184 break; 6185 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6186 *flg = mat->symmetry_eternal; 6187 break; 6188 default: 6189 break; 6190 } 6191 PetscFunctionReturn(PETSC_SUCCESS); 6192 } 6193 6194 /*@ 6195 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6196 this routine retains the old nonzero structure. 6197 6198 Logically Collective 6199 6200 Input Parameter: 6201 . mat - the matrix 6202 6203 Level: intermediate 6204 6205 Note: 6206 If the matrix was not preallocated then a default, likely poor preallocation will be set in the matrix, so this should be called after the preallocation phase. 6207 See the Performance chapter of the users manual for information on preallocating matrices. 6208 6209 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6210 @*/ 6211 PetscErrorCode MatZeroEntries(Mat mat) 6212 { 6213 PetscFunctionBegin; 6214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6215 PetscValidType(mat, 1); 6216 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6217 PetscCheck(mat->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for matrices where you have set values but not yet assembled"); 6218 MatCheckPreallocated(mat, 1); 6219 6220 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6221 PetscUseTypeMethod(mat, zeroentries); 6222 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6223 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6224 PetscFunctionReturn(PETSC_SUCCESS); 6225 } 6226 6227 /*@ 6228 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6229 of a set of rows and columns of a matrix. 6230 6231 Collective 6232 6233 Input Parameters: 6234 + mat - the matrix 6235 . numRows - the number of rows/columns to zero 6236 . rows - the global row indices 6237 . diag - value put in the diagonal of the eliminated rows 6238 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6239 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6240 6241 Level: intermediate 6242 6243 Notes: 6244 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6245 6246 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6247 The other entries of `b` will be adjusted by the known values of `x` times the corresponding matrix entries in the columns that are being eliminated 6248 6249 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6250 Krylov method to take advantage of the known solution on the zeroed rows. 6251 6252 For the parallel case, all processes that share the matrix (i.e., 6253 those in the communicator used for matrix creation) MUST call this 6254 routine, regardless of whether any rows being zeroed are owned by 6255 them. 6256 6257 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6258 removes them from the nonzero pattern. The nonzero pattern of the matrix can still change if a nonzero needs to be inserted on a diagonal entry that was previously 6259 missing. 6260 6261 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6262 list only rows local to itself). 6263 6264 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6265 6266 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6267 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6268 @*/ 6269 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6270 { 6271 PetscFunctionBegin; 6272 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6273 PetscValidType(mat, 1); 6274 if (numRows) PetscAssertPointer(rows, 3); 6275 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6276 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6277 MatCheckPreallocated(mat, 1); 6278 6279 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6280 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6281 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6282 PetscFunctionReturn(PETSC_SUCCESS); 6283 } 6284 6285 /*@ 6286 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6287 of a set of rows and columns of a matrix. 6288 6289 Collective 6290 6291 Input Parameters: 6292 + mat - the matrix 6293 . is - the rows to zero 6294 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6295 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6296 - b - optional vector of right-hand side, that will be adjusted by provided solution 6297 6298 Level: intermediate 6299 6300 Note: 6301 See `MatZeroRowsColumns()` for details on how this routine operates. 6302 6303 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6304 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6305 @*/ 6306 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6307 { 6308 PetscInt numRows; 6309 const PetscInt *rows; 6310 6311 PetscFunctionBegin; 6312 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6313 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6314 PetscValidType(mat, 1); 6315 PetscValidType(is, 2); 6316 PetscCall(ISGetLocalSize(is, &numRows)); 6317 PetscCall(ISGetIndices(is, &rows)); 6318 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6319 PetscCall(ISRestoreIndices(is, &rows)); 6320 PetscFunctionReturn(PETSC_SUCCESS); 6321 } 6322 6323 /*@ 6324 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6325 of a set of rows of a matrix. 6326 6327 Collective 6328 6329 Input Parameters: 6330 + mat - the matrix 6331 . numRows - the number of rows to zero 6332 . rows - the global row indices 6333 . diag - value put in the diagonal of the zeroed rows 6334 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6335 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6336 6337 Level: intermediate 6338 6339 Notes: 6340 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6341 6342 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6343 6344 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6345 Krylov method to take advantage of the known solution on the zeroed rows. 6346 6347 May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns) 6348 from the matrix. 6349 6350 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6351 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6352 formats this does not alter the nonzero structure. 6353 6354 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6355 of the matrix is not changed the values are 6356 merely zeroed. 6357 6358 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6359 formats can optionally remove the main diagonal entry from the 6360 nonzero structure as well, by passing 0.0 as the final argument). 6361 6362 For the parallel case, all processes that share the matrix (i.e., 6363 those in the communicator used for matrix creation) MUST call this 6364 routine, regardless of whether any rows being zeroed are owned by 6365 them. 6366 6367 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6368 list only rows local to itself). 6369 6370 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6371 owns that are to be zeroed. This saves a global synchronization in the implementation. 6372 6373 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6374 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6375 @*/ 6376 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6377 { 6378 PetscFunctionBegin; 6379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6380 PetscValidType(mat, 1); 6381 if (numRows) PetscAssertPointer(rows, 3); 6382 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6383 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6384 MatCheckPreallocated(mat, 1); 6385 6386 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6387 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6388 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6389 PetscFunctionReturn(PETSC_SUCCESS); 6390 } 6391 6392 /*@ 6393 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6394 of a set of rows of a matrix indicated by an `IS` 6395 6396 Collective 6397 6398 Input Parameters: 6399 + mat - the matrix 6400 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6401 . diag - value put in all diagonals of eliminated rows 6402 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6403 - b - optional vector of right-hand side, that will be adjusted by provided solution 6404 6405 Level: intermediate 6406 6407 Note: 6408 See `MatZeroRows()` for details on how this routine operates. 6409 6410 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6411 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6412 @*/ 6413 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6414 { 6415 PetscInt numRows = 0; 6416 const PetscInt *rows = NULL; 6417 6418 PetscFunctionBegin; 6419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6420 PetscValidType(mat, 1); 6421 if (is) { 6422 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6423 PetscCall(ISGetLocalSize(is, &numRows)); 6424 PetscCall(ISGetIndices(is, &rows)); 6425 } 6426 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6427 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6428 PetscFunctionReturn(PETSC_SUCCESS); 6429 } 6430 6431 /*@ 6432 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6433 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6434 6435 Collective 6436 6437 Input Parameters: 6438 + mat - the matrix 6439 . numRows - the number of rows to remove 6440 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6441 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6442 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6443 - b - optional vector of right-hand side, that will be adjusted by provided solution 6444 6445 Level: intermediate 6446 6447 Notes: 6448 See `MatZeroRows()` for details on how this routine operates. 6449 6450 The grid coordinates are across the entire grid, not just the local portion 6451 6452 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6453 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6454 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6455 `DM_BOUNDARY_PERIODIC` boundary type. 6456 6457 For indices that don't mean anything for your case (like the `k` index when working in 2d) or the `c` index when you have 6458 a single value per point) you can skip filling those indices. 6459 6460 Fortran Note: 6461 `idxm` and `idxn` should be declared as 6462 .vb 6463 MatStencil idxm(4, m) 6464 .ve 6465 and the values inserted using 6466 .vb 6467 idxm(MatStencil_i, 1) = i 6468 idxm(MatStencil_j, 1) = j 6469 idxm(MatStencil_k, 1) = k 6470 idxm(MatStencil_c, 1) = c 6471 etc 6472 .ve 6473 6474 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6475 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6476 @*/ 6477 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6478 { 6479 PetscInt dim = mat->stencil.dim; 6480 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6481 PetscInt *dims = mat->stencil.dims + 1; 6482 PetscInt *starts = mat->stencil.starts; 6483 PetscInt *dxm = (PetscInt *)rows; 6484 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6485 6486 PetscFunctionBegin; 6487 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6488 PetscValidType(mat, 1); 6489 if (numRows) PetscAssertPointer(rows, 3); 6490 6491 PetscCall(PetscMalloc1(numRows, &jdxm)); 6492 for (i = 0; i < numRows; ++i) { 6493 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6494 for (j = 0; j < 3 - sdim; ++j) dxm++; 6495 /* Local index in X dir */ 6496 tmp = *dxm++ - starts[0]; 6497 /* Loop over remaining dimensions */ 6498 for (j = 0; j < dim - 1; ++j) { 6499 /* If nonlocal, set index to be negative */ 6500 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6501 /* Update local index */ 6502 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6503 } 6504 /* Skip component slot if necessary */ 6505 if (mat->stencil.noc) dxm++; 6506 /* Local row number */ 6507 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6508 } 6509 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6510 PetscCall(PetscFree(jdxm)); 6511 PetscFunctionReturn(PETSC_SUCCESS); 6512 } 6513 6514 /*@ 6515 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6516 of a set of rows and columns of a matrix. 6517 6518 Collective 6519 6520 Input Parameters: 6521 + mat - the matrix 6522 . numRows - the number of rows/columns to remove 6523 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6524 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6525 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6526 - b - optional vector of right-hand side, that will be adjusted by provided solution 6527 6528 Level: intermediate 6529 6530 Notes: 6531 See `MatZeroRowsColumns()` for details on how this routine operates. 6532 6533 The grid coordinates are across the entire grid, not just the local portion 6534 6535 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6536 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6537 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6538 `DM_BOUNDARY_PERIODIC` boundary type. 6539 6540 For indices that don't mean anything for your case (like the `k` index when working in 2d) or the `c` index when you have 6541 a single value per point) you can skip filling those indices. 6542 6543 Fortran Note: 6544 `idxm` and `idxn` should be declared as 6545 .vb 6546 MatStencil idxm(4, m) 6547 .ve 6548 and the values inserted using 6549 .vb 6550 idxm(MatStencil_i, 1) = i 6551 idxm(MatStencil_j, 1) = j 6552 idxm(MatStencil_k, 1) = k 6553 idxm(MatStencil_c, 1) = c 6554 etc 6555 .ve 6556 6557 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6558 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6559 @*/ 6560 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6561 { 6562 PetscInt dim = mat->stencil.dim; 6563 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6564 PetscInt *dims = mat->stencil.dims + 1; 6565 PetscInt *starts = mat->stencil.starts; 6566 PetscInt *dxm = (PetscInt *)rows; 6567 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6568 6569 PetscFunctionBegin; 6570 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6571 PetscValidType(mat, 1); 6572 if (numRows) PetscAssertPointer(rows, 3); 6573 6574 PetscCall(PetscMalloc1(numRows, &jdxm)); 6575 for (i = 0; i < numRows; ++i) { 6576 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6577 for (j = 0; j < 3 - sdim; ++j) dxm++; 6578 /* Local index in X dir */ 6579 tmp = *dxm++ - starts[0]; 6580 /* Loop over remaining dimensions */ 6581 for (j = 0; j < dim - 1; ++j) { 6582 /* If nonlocal, set index to be negative */ 6583 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6584 /* Update local index */ 6585 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6586 } 6587 /* Skip component slot if necessary */ 6588 if (mat->stencil.noc) dxm++; 6589 /* Local row number */ 6590 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6591 } 6592 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6593 PetscCall(PetscFree(jdxm)); 6594 PetscFunctionReturn(PETSC_SUCCESS); 6595 } 6596 6597 /*@ 6598 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6599 of a set of rows of a matrix; using local numbering of rows. 6600 6601 Collective 6602 6603 Input Parameters: 6604 + mat - the matrix 6605 . numRows - the number of rows to remove 6606 . rows - the local row indices 6607 . diag - value put in all diagonals of eliminated rows 6608 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6609 - b - optional vector of right-hand side, that will be adjusted by provided solution 6610 6611 Level: intermediate 6612 6613 Notes: 6614 Before calling `MatZeroRowsLocal()`, the user must first set the 6615 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6616 6617 See `MatZeroRows()` for details on how this routine operates. 6618 6619 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6620 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6621 @*/ 6622 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6623 { 6624 PetscFunctionBegin; 6625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6626 PetscValidType(mat, 1); 6627 if (numRows) PetscAssertPointer(rows, 3); 6628 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6629 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6630 MatCheckPreallocated(mat, 1); 6631 6632 if (mat->ops->zerorowslocal) { 6633 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6634 } else { 6635 IS is, newis; 6636 const PetscInt *newRows; 6637 6638 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6639 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6640 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6641 PetscCall(ISGetIndices(newis, &newRows)); 6642 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6643 PetscCall(ISRestoreIndices(newis, &newRows)); 6644 PetscCall(ISDestroy(&newis)); 6645 PetscCall(ISDestroy(&is)); 6646 } 6647 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6648 PetscFunctionReturn(PETSC_SUCCESS); 6649 } 6650 6651 /*@ 6652 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6653 of a set of rows of a matrix; using local numbering of rows. 6654 6655 Collective 6656 6657 Input Parameters: 6658 + mat - the matrix 6659 . is - index set of rows to remove 6660 . diag - value put in all diagonals of eliminated rows 6661 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6662 - b - optional vector of right-hand side, that will be adjusted by provided solution 6663 6664 Level: intermediate 6665 6666 Notes: 6667 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6668 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6669 6670 See `MatZeroRows()` for details on how this routine operates. 6671 6672 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6673 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6674 @*/ 6675 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6676 { 6677 PetscInt numRows; 6678 const PetscInt *rows; 6679 6680 PetscFunctionBegin; 6681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6682 PetscValidType(mat, 1); 6683 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6684 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6685 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6686 MatCheckPreallocated(mat, 1); 6687 6688 PetscCall(ISGetLocalSize(is, &numRows)); 6689 PetscCall(ISGetIndices(is, &rows)); 6690 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6691 PetscCall(ISRestoreIndices(is, &rows)); 6692 PetscFunctionReturn(PETSC_SUCCESS); 6693 } 6694 6695 /*@ 6696 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6697 of a set of rows and columns of a matrix; using local numbering of rows. 6698 6699 Collective 6700 6701 Input Parameters: 6702 + mat - the matrix 6703 . numRows - the number of rows to remove 6704 . rows - the global row indices 6705 . diag - value put in all diagonals of eliminated rows 6706 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6707 - b - optional vector of right-hand side, that will be adjusted by provided solution 6708 6709 Level: intermediate 6710 6711 Notes: 6712 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6713 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6714 6715 See `MatZeroRowsColumns()` for details on how this routine operates. 6716 6717 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6718 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6719 @*/ 6720 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6721 { 6722 IS is, newis; 6723 const PetscInt *newRows; 6724 6725 PetscFunctionBegin; 6726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6727 PetscValidType(mat, 1); 6728 if (numRows) PetscAssertPointer(rows, 3); 6729 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6730 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6731 MatCheckPreallocated(mat, 1); 6732 6733 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6734 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6735 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6736 PetscCall(ISGetIndices(newis, &newRows)); 6737 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6738 PetscCall(ISRestoreIndices(newis, &newRows)); 6739 PetscCall(ISDestroy(&newis)); 6740 PetscCall(ISDestroy(&is)); 6741 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6742 PetscFunctionReturn(PETSC_SUCCESS); 6743 } 6744 6745 /*@ 6746 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6747 of a set of rows and columns of a matrix; using local numbering of rows. 6748 6749 Collective 6750 6751 Input Parameters: 6752 + mat - the matrix 6753 . is - index set of rows to remove 6754 . diag - value put in all diagonals of eliminated rows 6755 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6756 - b - optional vector of right-hand side, that will be adjusted by provided solution 6757 6758 Level: intermediate 6759 6760 Notes: 6761 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6762 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6763 6764 See `MatZeroRowsColumns()` for details on how this routine operates. 6765 6766 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6767 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6768 @*/ 6769 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6770 { 6771 PetscInt numRows; 6772 const PetscInt *rows; 6773 6774 PetscFunctionBegin; 6775 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6776 PetscValidType(mat, 1); 6777 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6778 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6779 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6780 MatCheckPreallocated(mat, 1); 6781 6782 PetscCall(ISGetLocalSize(is, &numRows)); 6783 PetscCall(ISGetIndices(is, &rows)); 6784 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6785 PetscCall(ISRestoreIndices(is, &rows)); 6786 PetscFunctionReturn(PETSC_SUCCESS); 6787 } 6788 6789 /*@ 6790 MatGetSize - Returns the numbers of rows and columns in a matrix. 6791 6792 Not Collective 6793 6794 Input Parameter: 6795 . mat - the matrix 6796 6797 Output Parameters: 6798 + m - the number of global rows 6799 - n - the number of global columns 6800 6801 Level: beginner 6802 6803 Note: 6804 Both output parameters can be `NULL` on input. 6805 6806 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6807 @*/ 6808 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6809 { 6810 PetscFunctionBegin; 6811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6812 if (m) *m = mat->rmap->N; 6813 if (n) *n = mat->cmap->N; 6814 PetscFunctionReturn(PETSC_SUCCESS); 6815 } 6816 6817 /*@ 6818 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6819 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6820 6821 Not Collective 6822 6823 Input Parameter: 6824 . mat - the matrix 6825 6826 Output Parameters: 6827 + m - the number of local rows, use `NULL` to not obtain this value 6828 - n - the number of local columns, use `NULL` to not obtain this value 6829 6830 Level: beginner 6831 6832 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6833 @*/ 6834 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6835 { 6836 PetscFunctionBegin; 6837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6838 if (m) PetscAssertPointer(m, 2); 6839 if (n) PetscAssertPointer(n, 3); 6840 if (m) *m = mat->rmap->n; 6841 if (n) *n = mat->cmap->n; 6842 PetscFunctionReturn(PETSC_SUCCESS); 6843 } 6844 6845 /*@ 6846 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6847 vector one multiplies this matrix by that are owned by this processor. 6848 6849 Not Collective, unless matrix has not been allocated, then collective 6850 6851 Input Parameter: 6852 . mat - the matrix 6853 6854 Output Parameters: 6855 + m - the global index of the first local column, use `NULL` to not obtain this value 6856 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6857 6858 Level: developer 6859 6860 Notes: 6861 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6862 6863 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6864 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6865 6866 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6867 the local values in the matrix. 6868 6869 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6870 Layouts](sec_matlayout) for details on matrix layouts. 6871 6872 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6873 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6874 @*/ 6875 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6876 { 6877 PetscFunctionBegin; 6878 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6879 PetscValidType(mat, 1); 6880 if (m) PetscAssertPointer(m, 2); 6881 if (n) PetscAssertPointer(n, 3); 6882 MatCheckPreallocated(mat, 1); 6883 if (m) *m = mat->cmap->rstart; 6884 if (n) *n = mat->cmap->rend; 6885 PetscFunctionReturn(PETSC_SUCCESS); 6886 } 6887 6888 /*@ 6889 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6890 this MPI process. 6891 6892 Not Collective 6893 6894 Input Parameter: 6895 . mat - the matrix 6896 6897 Output Parameters: 6898 + m - the global index of the first local row, use `NULL` to not obtain this value 6899 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6900 6901 Level: beginner 6902 6903 Notes: 6904 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6905 6906 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6907 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6908 6909 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6910 the local values in the matrix. 6911 6912 The high argument is one more than the last element stored locally. 6913 6914 For all matrices it returns the range of matrix rows associated with rows of a vector that 6915 would contain the result of a matrix vector product with this matrix. See [Matrix 6916 Layouts](sec_matlayout) for details on matrix layouts. 6917 6918 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6919 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6920 @*/ 6921 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6922 { 6923 PetscFunctionBegin; 6924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6925 PetscValidType(mat, 1); 6926 if (m) PetscAssertPointer(m, 2); 6927 if (n) PetscAssertPointer(n, 3); 6928 MatCheckPreallocated(mat, 1); 6929 if (m) *m = mat->rmap->rstart; 6930 if (n) *n = mat->rmap->rend; 6931 PetscFunctionReturn(PETSC_SUCCESS); 6932 } 6933 6934 /*@C 6935 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6936 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6937 6938 Not Collective, unless matrix has not been allocated 6939 6940 Input Parameter: 6941 . mat - the matrix 6942 6943 Output Parameter: 6944 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6945 where `size` is the number of MPI processes used by `mat` 6946 6947 Level: beginner 6948 6949 Notes: 6950 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6951 6952 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6953 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6954 6955 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6956 the local values in the matrix. 6957 6958 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6959 would contain the result of a matrix vector product with this matrix. See [Matrix 6960 Layouts](sec_matlayout) for details on matrix layouts. 6961 6962 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6963 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6964 `DMDAGetGhostCorners()`, `DM` 6965 @*/ 6966 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6967 { 6968 PetscFunctionBegin; 6969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6970 PetscValidType(mat, 1); 6971 MatCheckPreallocated(mat, 1); 6972 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6973 PetscFunctionReturn(PETSC_SUCCESS); 6974 } 6975 6976 /*@C 6977 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6978 vector one multiplies this vector by that are owned by each processor. 6979 6980 Not Collective, unless matrix has not been allocated 6981 6982 Input Parameter: 6983 . mat - the matrix 6984 6985 Output Parameter: 6986 . ranges - start of each processors portion plus one more than the total length at the end 6987 6988 Level: beginner 6989 6990 Notes: 6991 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6992 6993 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6994 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6995 6996 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6997 the local values in the matrix. 6998 6999 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7000 Layouts](sec_matlayout) for details on matrix layouts. 7001 7002 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7003 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7004 `DMDAGetGhostCorners()`, `DM` 7005 @*/ 7006 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7007 { 7008 PetscFunctionBegin; 7009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7010 PetscValidType(mat, 1); 7011 MatCheckPreallocated(mat, 1); 7012 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7013 PetscFunctionReturn(PETSC_SUCCESS); 7014 } 7015 7016 /*@ 7017 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7018 7019 Not Collective 7020 7021 Input Parameter: 7022 . A - matrix 7023 7024 Output Parameters: 7025 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7026 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7027 7028 Level: intermediate 7029 7030 Note: 7031 You should call `ISDestroy()` on the returned `IS` 7032 7033 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7034 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7035 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7036 details on matrix layouts. 7037 7038 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7039 @*/ 7040 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7041 { 7042 PetscErrorCode (*f)(Mat, IS *, IS *); 7043 7044 PetscFunctionBegin; 7045 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7046 PetscValidType(A, 1); 7047 MatCheckPreallocated(A, 1); 7048 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7049 if (f) { 7050 PetscCall((*f)(A, rows, cols)); 7051 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7052 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7053 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7054 } 7055 PetscFunctionReturn(PETSC_SUCCESS); 7056 } 7057 7058 /*@ 7059 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7060 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7061 to complete the factorization. 7062 7063 Collective 7064 7065 Input Parameters: 7066 + fact - the factorized matrix obtained with `MatGetFactor()` 7067 . mat - the matrix 7068 . row - row permutation 7069 . col - column permutation 7070 - info - structure containing 7071 .vb 7072 levels - number of levels of fill. 7073 expected fill - as ratio of original fill. 7074 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7075 missing diagonal entries) 7076 .ve 7077 7078 Level: developer 7079 7080 Notes: 7081 See [Matrix Factorization](sec_matfactor) for additional information. 7082 7083 Most users should employ the `KSP` interface for linear solvers 7084 instead of working directly with matrix algebra routines such as this. 7085 See, e.g., `KSPCreate()`. 7086 7087 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7088 7089 Fortran Note: 7090 A valid (non-null) `info` argument must be provided 7091 7092 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7093 `MatGetOrdering()`, `MatFactorInfo` 7094 @*/ 7095 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7096 { 7097 PetscFunctionBegin; 7098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7099 PetscValidType(mat, 2); 7100 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7101 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7102 PetscAssertPointer(info, 5); 7103 PetscAssertPointer(fact, 1); 7104 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7105 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7106 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7107 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7108 MatCheckPreallocated(mat, 2); 7109 7110 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7111 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7112 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7113 PetscFunctionReturn(PETSC_SUCCESS); 7114 } 7115 7116 /*@ 7117 MatICCFactorSymbolic - Performs symbolic incomplete 7118 Cholesky factorization for a symmetric matrix. Use 7119 `MatCholeskyFactorNumeric()` to complete the factorization. 7120 7121 Collective 7122 7123 Input Parameters: 7124 + fact - the factorized matrix obtained with `MatGetFactor()` 7125 . mat - the matrix to be factored 7126 . perm - row and column permutation 7127 - info - structure containing 7128 .vb 7129 levels - number of levels of fill. 7130 expected fill - as ratio of original fill. 7131 .ve 7132 7133 Level: developer 7134 7135 Notes: 7136 Most users should employ the `KSP` interface for linear solvers 7137 instead of working directly with matrix algebra routines such as this. 7138 See, e.g., `KSPCreate()`. 7139 7140 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7141 7142 Fortran Note: 7143 A valid (non-null) `info` argument must be provided 7144 7145 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7146 @*/ 7147 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7148 { 7149 PetscFunctionBegin; 7150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7151 PetscValidType(mat, 2); 7152 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7153 PetscAssertPointer(info, 4); 7154 PetscAssertPointer(fact, 1); 7155 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7156 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7157 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7158 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7159 MatCheckPreallocated(mat, 2); 7160 7161 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7162 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7164 PetscFunctionReturn(PETSC_SUCCESS); 7165 } 7166 7167 /*@C 7168 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7169 points to an array of valid matrices, they may be reused to store the new 7170 submatrices. 7171 7172 Collective 7173 7174 Input Parameters: 7175 + mat - the matrix 7176 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7177 . irow - index set of rows to extract 7178 . icol - index set of columns to extract 7179 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7180 7181 Output Parameter: 7182 . submat - the array of submatrices 7183 7184 Level: advanced 7185 7186 Notes: 7187 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7188 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7189 to extract a parallel submatrix. 7190 7191 Some matrix types place restrictions on the row and column 7192 indices, such as that they be sorted or that they be equal to each other. 7193 7194 The index sets may not have duplicate entries. 7195 7196 When extracting submatrices from a parallel matrix, each processor can 7197 form a different submatrix by setting the rows and columns of its 7198 individual index sets according to the local submatrix desired. 7199 7200 When finished using the submatrices, the user should destroy 7201 them with `MatDestroySubMatrices()`. 7202 7203 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7204 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7205 7206 This routine creates the matrices in submat; you should NOT create them before 7207 calling it. It also allocates the array of matrix pointers submat. 7208 7209 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7210 request one row/column in a block, they must request all rows/columns that are in 7211 that block. For example, if the block size is 2 you cannot request just row 0 and 7212 column 0. 7213 7214 Fortran Note: 7215 .vb 7216 Mat, pointer :: submat(:) 7217 .ve 7218 7219 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7220 @*/ 7221 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7222 { 7223 PetscInt i; 7224 PetscBool eq; 7225 7226 PetscFunctionBegin; 7227 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7228 PetscValidType(mat, 1); 7229 if (n) { 7230 PetscAssertPointer(irow, 3); 7231 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7232 PetscAssertPointer(icol, 4); 7233 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7234 } 7235 PetscAssertPointer(submat, 6); 7236 if (n && scall == MAT_REUSE_MATRIX) { 7237 PetscAssertPointer(*submat, 6); 7238 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7239 } 7240 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7241 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7242 MatCheckPreallocated(mat, 1); 7243 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7244 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7245 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7246 for (i = 0; i < n; i++) { 7247 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7248 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7249 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7250 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7251 if (mat->boundtocpu && mat->bindingpropagates) { 7252 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7253 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7254 } 7255 #endif 7256 } 7257 PetscFunctionReturn(PETSC_SUCCESS); 7258 } 7259 7260 /*@C 7261 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7262 7263 Collective 7264 7265 Input Parameters: 7266 + mat - the matrix 7267 . n - the number of submatrixes to be extracted 7268 . irow - index set of rows to extract 7269 . icol - index set of columns to extract 7270 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7271 7272 Output Parameter: 7273 . submat - the array of submatrices 7274 7275 Level: advanced 7276 7277 Note: 7278 This is used by `PCGASM` 7279 7280 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7281 @*/ 7282 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7283 { 7284 PetscInt i; 7285 PetscBool eq; 7286 7287 PetscFunctionBegin; 7288 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7289 PetscValidType(mat, 1); 7290 if (n) { 7291 PetscAssertPointer(irow, 3); 7292 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7293 PetscAssertPointer(icol, 4); 7294 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7295 } 7296 PetscAssertPointer(submat, 6); 7297 if (n && scall == MAT_REUSE_MATRIX) { 7298 PetscAssertPointer(*submat, 6); 7299 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7300 } 7301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7303 MatCheckPreallocated(mat, 1); 7304 7305 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7306 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7307 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7308 for (i = 0; i < n; i++) { 7309 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7310 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7311 } 7312 PetscFunctionReturn(PETSC_SUCCESS); 7313 } 7314 7315 /*@C 7316 MatDestroyMatrices - Destroys an array of matrices 7317 7318 Collective 7319 7320 Input Parameters: 7321 + n - the number of local matrices 7322 - mat - the matrices (this is a pointer to the array of matrices) 7323 7324 Level: advanced 7325 7326 Notes: 7327 Frees not only the matrices, but also the array that contains the matrices 7328 7329 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7330 7331 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7332 @*/ 7333 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7334 { 7335 PetscInt i; 7336 7337 PetscFunctionBegin; 7338 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7339 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7340 PetscAssertPointer(mat, 2); 7341 7342 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7343 7344 /* memory is allocated even if n = 0 */ 7345 PetscCall(PetscFree(*mat)); 7346 PetscFunctionReturn(PETSC_SUCCESS); 7347 } 7348 7349 /*@C 7350 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7351 7352 Collective 7353 7354 Input Parameters: 7355 + n - the number of local matrices 7356 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7357 7358 Level: advanced 7359 7360 Note: 7361 Frees not only the matrices, but also the array that contains the matrices 7362 7363 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7364 @*/ 7365 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7366 { 7367 Mat mat0; 7368 7369 PetscFunctionBegin; 7370 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7371 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7372 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7373 PetscAssertPointer(mat, 2); 7374 7375 mat0 = (*mat)[0]; 7376 if (mat0 && mat0->ops->destroysubmatrices) { 7377 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7378 } else { 7379 PetscCall(MatDestroyMatrices(n, mat)); 7380 } 7381 PetscFunctionReturn(PETSC_SUCCESS); 7382 } 7383 7384 /*@ 7385 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7386 7387 Collective 7388 7389 Input Parameter: 7390 . mat - the matrix 7391 7392 Output Parameter: 7393 . matstruct - the sequential matrix with the nonzero structure of `mat` 7394 7395 Level: developer 7396 7397 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7398 @*/ 7399 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7400 { 7401 PetscFunctionBegin; 7402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7403 PetscAssertPointer(matstruct, 2); 7404 7405 PetscValidType(mat, 1); 7406 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7407 MatCheckPreallocated(mat, 1); 7408 7409 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7410 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7411 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7412 PetscFunctionReturn(PETSC_SUCCESS); 7413 } 7414 7415 /*@C 7416 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7417 7418 Collective 7419 7420 Input Parameter: 7421 . mat - the matrix 7422 7423 Level: advanced 7424 7425 Note: 7426 This is not needed, one can just call `MatDestroy()` 7427 7428 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7429 @*/ 7430 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7431 { 7432 PetscFunctionBegin; 7433 PetscAssertPointer(mat, 1); 7434 PetscCall(MatDestroy(mat)); 7435 PetscFunctionReturn(PETSC_SUCCESS); 7436 } 7437 7438 /*@ 7439 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7440 replaces the index sets by larger ones that represent submatrices with 7441 additional overlap. 7442 7443 Collective 7444 7445 Input Parameters: 7446 + mat - the matrix 7447 . n - the number of index sets 7448 . is - the array of index sets (these index sets will changed during the call) 7449 - ov - the additional overlap requested 7450 7451 Options Database Key: 7452 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7453 7454 Level: developer 7455 7456 Note: 7457 The computed overlap preserves the matrix block sizes when the blocks are square. 7458 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7459 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7460 7461 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7462 @*/ 7463 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7464 { 7465 PetscInt i, bs, cbs; 7466 7467 PetscFunctionBegin; 7468 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7469 PetscValidType(mat, 1); 7470 PetscValidLogicalCollectiveInt(mat, n, 2); 7471 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7472 if (n) { 7473 PetscAssertPointer(is, 3); 7474 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7475 } 7476 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7477 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7478 MatCheckPreallocated(mat, 1); 7479 7480 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7481 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7482 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7483 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7484 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7485 if (bs == cbs) { 7486 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7487 } 7488 PetscFunctionReturn(PETSC_SUCCESS); 7489 } 7490 7491 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7492 7493 /*@ 7494 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7495 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7496 additional overlap. 7497 7498 Collective 7499 7500 Input Parameters: 7501 + mat - the matrix 7502 . n - the number of index sets 7503 . is - the array of index sets (these index sets will changed during the call) 7504 - ov - the additional overlap requested 7505 7506 ` Options Database Key: 7507 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7508 7509 Level: developer 7510 7511 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7512 @*/ 7513 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7514 { 7515 PetscInt i; 7516 7517 PetscFunctionBegin; 7518 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7519 PetscValidType(mat, 1); 7520 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7521 if (n) { 7522 PetscAssertPointer(is, 3); 7523 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7524 } 7525 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7526 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7527 MatCheckPreallocated(mat, 1); 7528 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7529 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7530 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7531 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7532 PetscFunctionReturn(PETSC_SUCCESS); 7533 } 7534 7535 /*@ 7536 MatGetBlockSize - Returns the matrix block size. 7537 7538 Not Collective 7539 7540 Input Parameter: 7541 . mat - the matrix 7542 7543 Output Parameter: 7544 . bs - block size 7545 7546 Level: intermediate 7547 7548 Notes: 7549 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7550 7551 If the block size has not been set yet this routine returns 1. 7552 7553 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7554 @*/ 7555 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7556 { 7557 PetscFunctionBegin; 7558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7559 PetscAssertPointer(bs, 2); 7560 *bs = mat->rmap->bs; 7561 PetscFunctionReturn(PETSC_SUCCESS); 7562 } 7563 7564 /*@ 7565 MatGetBlockSizes - Returns the matrix block row and column sizes. 7566 7567 Not Collective 7568 7569 Input Parameter: 7570 . mat - the matrix 7571 7572 Output Parameters: 7573 + rbs - row block size 7574 - cbs - column block size 7575 7576 Level: intermediate 7577 7578 Notes: 7579 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7580 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7581 7582 If a block size has not been set yet this routine returns 1. 7583 7584 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7585 @*/ 7586 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7587 { 7588 PetscFunctionBegin; 7589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7590 if (rbs) PetscAssertPointer(rbs, 2); 7591 if (cbs) PetscAssertPointer(cbs, 3); 7592 if (rbs) *rbs = mat->rmap->bs; 7593 if (cbs) *cbs = mat->cmap->bs; 7594 PetscFunctionReturn(PETSC_SUCCESS); 7595 } 7596 7597 /*@ 7598 MatSetBlockSize - Sets the matrix block size. 7599 7600 Logically Collective 7601 7602 Input Parameters: 7603 + mat - the matrix 7604 - bs - block size 7605 7606 Level: intermediate 7607 7608 Notes: 7609 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7610 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7611 7612 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7613 is compatible with the matrix local sizes. 7614 7615 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7616 @*/ 7617 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7618 { 7619 PetscFunctionBegin; 7620 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7621 PetscValidLogicalCollectiveInt(mat, bs, 2); 7622 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7623 PetscFunctionReturn(PETSC_SUCCESS); 7624 } 7625 7626 typedef struct { 7627 PetscInt n; 7628 IS *is; 7629 Mat *mat; 7630 PetscObjectState nonzerostate; 7631 Mat C; 7632 } EnvelopeData; 7633 7634 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7635 { 7636 EnvelopeData *edata = (EnvelopeData *)*ptr; 7637 7638 PetscFunctionBegin; 7639 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7640 PetscCall(PetscFree(edata->is)); 7641 PetscCall(PetscFree(edata)); 7642 PetscFunctionReturn(PETSC_SUCCESS); 7643 } 7644 7645 /*@ 7646 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7647 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7648 7649 Collective 7650 7651 Input Parameter: 7652 . mat - the matrix 7653 7654 Level: intermediate 7655 7656 Notes: 7657 There can be zeros within the blocks 7658 7659 The blocks can overlap between processes, including laying on more than two processes 7660 7661 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7662 @*/ 7663 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7664 { 7665 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7666 PetscInt *diag, *odiag, sc; 7667 VecScatter scatter; 7668 PetscScalar *seqv; 7669 const PetscScalar *parv; 7670 const PetscInt *ia, *ja; 7671 PetscBool set, flag, done; 7672 Mat AA = mat, A; 7673 MPI_Comm comm; 7674 PetscMPIInt rank, size, tag; 7675 MPI_Status status; 7676 PetscContainer container; 7677 EnvelopeData *edata; 7678 Vec seq, par; 7679 IS isglobal; 7680 7681 PetscFunctionBegin; 7682 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7683 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7684 if (!set || !flag) { 7685 /* TODO: only needs nonzero structure of transpose */ 7686 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7687 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7688 } 7689 PetscCall(MatAIJGetLocalMat(AA, &A)); 7690 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7691 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7692 7693 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7694 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7695 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7696 PetscCallMPI(MPI_Comm_size(comm, &size)); 7697 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7698 7699 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7700 7701 if (rank > 0) { 7702 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7703 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7704 } 7705 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7706 for (i = 0; i < n; i++) { 7707 env = PetscMax(env, ja[ia[i + 1] - 1]); 7708 II = rstart + i; 7709 if (env == II) { 7710 starts[lblocks] = tbs; 7711 sizes[lblocks++] = 1 + II - tbs; 7712 tbs = 1 + II; 7713 } 7714 } 7715 if (rank < size - 1) { 7716 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7717 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7718 } 7719 7720 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7721 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7722 PetscCall(MatDestroy(&A)); 7723 7724 PetscCall(PetscNew(&edata)); 7725 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7726 edata->n = lblocks; 7727 /* create IS needed for extracting blocks from the original matrix */ 7728 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7729 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7730 7731 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7732 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7733 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7734 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7735 PetscCall(MatSetType(edata->C, MATAIJ)); 7736 7737 /* Communicate the start and end of each row, from each block to the correct rank */ 7738 /* TODO: Use PetscSF instead of VecScatter */ 7739 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7740 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7741 PetscCall(VecGetArrayWrite(seq, &seqv)); 7742 for (PetscInt i = 0; i < lblocks; i++) { 7743 for (PetscInt j = 0; j < sizes[i]; j++) { 7744 seqv[cnt] = starts[i]; 7745 seqv[cnt + 1] = starts[i] + sizes[i]; 7746 cnt += 2; 7747 } 7748 } 7749 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7750 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7751 sc -= cnt; 7752 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7753 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7754 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7755 PetscCall(ISDestroy(&isglobal)); 7756 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7757 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7758 PetscCall(VecScatterDestroy(&scatter)); 7759 PetscCall(VecDestroy(&seq)); 7760 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7761 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7762 PetscCall(VecGetArrayRead(par, &parv)); 7763 cnt = 0; 7764 PetscCall(MatGetSize(mat, NULL, &n)); 7765 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7766 PetscInt start, end, d = 0, od = 0; 7767 7768 start = (PetscInt)PetscRealPart(parv[cnt]); 7769 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7770 cnt += 2; 7771 7772 if (start < cstart) { 7773 od += cstart - start + n - cend; 7774 d += cend - cstart; 7775 } else if (start < cend) { 7776 od += n - cend; 7777 d += cend - start; 7778 } else od += n - start; 7779 if (end <= cstart) { 7780 od -= cstart - end + n - cend; 7781 d -= cend - cstart; 7782 } else if (end < cend) { 7783 od -= n - cend; 7784 d -= cend - end; 7785 } else od -= n - end; 7786 7787 odiag[i] = od; 7788 diag[i] = d; 7789 } 7790 PetscCall(VecRestoreArrayRead(par, &parv)); 7791 PetscCall(VecDestroy(&par)); 7792 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7793 PetscCall(PetscFree2(diag, odiag)); 7794 PetscCall(PetscFree2(sizes, starts)); 7795 7796 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7797 PetscCall(PetscContainerSetPointer(container, edata)); 7798 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7799 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7800 PetscCall(PetscObjectDereference((PetscObject)container)); 7801 PetscFunctionReturn(PETSC_SUCCESS); 7802 } 7803 7804 /*@ 7805 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7806 7807 Collective 7808 7809 Input Parameters: 7810 + A - the matrix 7811 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7812 7813 Output Parameter: 7814 . C - matrix with inverted block diagonal of `A` 7815 7816 Level: advanced 7817 7818 Note: 7819 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7820 7821 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7822 @*/ 7823 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7824 { 7825 PetscContainer container; 7826 EnvelopeData *edata; 7827 PetscObjectState nonzerostate; 7828 7829 PetscFunctionBegin; 7830 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7831 if (!container) { 7832 PetscCall(MatComputeVariableBlockEnvelope(A)); 7833 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7834 } 7835 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7836 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7837 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7838 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7839 7840 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7841 *C = edata->C; 7842 7843 for (PetscInt i = 0; i < edata->n; i++) { 7844 Mat D; 7845 PetscScalar *dvalues; 7846 7847 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7848 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7849 PetscCall(MatSeqDenseInvert(D)); 7850 PetscCall(MatDenseGetArray(D, &dvalues)); 7851 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7852 PetscCall(MatDestroy(&D)); 7853 } 7854 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7855 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7856 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7857 PetscFunctionReturn(PETSC_SUCCESS); 7858 } 7859 7860 /*@ 7861 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7862 7863 Not Collective 7864 7865 Input Parameters: 7866 + mat - the matrix 7867 . nblocks - the number of blocks on this process, each block can only exist on a single process 7868 - bsizes - the block sizes 7869 7870 Level: intermediate 7871 7872 Notes: 7873 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7874 7875 Each variable point-block set of degrees of freedom must live on a single MPI process. That is a point block cannot straddle two MPI processes. 7876 7877 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7878 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7879 @*/ 7880 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7881 { 7882 PetscInt ncnt = 0, nlocal; 7883 7884 PetscFunctionBegin; 7885 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7886 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7887 PetscCheck(nblocks >= 0 && nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", nblocks, nlocal); 7888 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7889 PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal); 7890 PetscCall(PetscFree(mat->bsizes)); 7891 mat->nblocks = nblocks; 7892 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7893 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7894 PetscFunctionReturn(PETSC_SUCCESS); 7895 } 7896 7897 /*@C 7898 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7899 7900 Not Collective; No Fortran Support 7901 7902 Input Parameter: 7903 . mat - the matrix 7904 7905 Output Parameters: 7906 + nblocks - the number of blocks on this process 7907 - bsizes - the block sizes 7908 7909 Level: intermediate 7910 7911 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7912 @*/ 7913 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7914 { 7915 PetscFunctionBegin; 7916 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7917 if (nblocks) *nblocks = mat->nblocks; 7918 if (bsizes) *bsizes = mat->bsizes; 7919 PetscFunctionReturn(PETSC_SUCCESS); 7920 } 7921 7922 /*@ 7923 MatSetBlockSizes - Sets the matrix block row and column sizes. 7924 7925 Logically Collective 7926 7927 Input Parameters: 7928 + mat - the matrix 7929 . rbs - row block size 7930 - cbs - column block size 7931 7932 Level: intermediate 7933 7934 Notes: 7935 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7936 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7937 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7938 7939 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7940 are compatible with the matrix local sizes. 7941 7942 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7943 7944 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7945 @*/ 7946 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7947 { 7948 PetscFunctionBegin; 7949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7950 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7951 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7952 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7953 if (mat->rmap->refcnt) { 7954 ISLocalToGlobalMapping l2g = NULL; 7955 PetscLayout nmap = NULL; 7956 7957 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7958 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7959 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7960 mat->rmap = nmap; 7961 mat->rmap->mapping = l2g; 7962 } 7963 if (mat->cmap->refcnt) { 7964 ISLocalToGlobalMapping l2g = NULL; 7965 PetscLayout nmap = NULL; 7966 7967 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7968 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7969 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7970 mat->cmap = nmap; 7971 mat->cmap->mapping = l2g; 7972 } 7973 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7974 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7975 PetscFunctionReturn(PETSC_SUCCESS); 7976 } 7977 7978 /*@ 7979 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7980 7981 Logically Collective 7982 7983 Input Parameters: 7984 + mat - the matrix 7985 . fromRow - matrix from which to copy row block size 7986 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7987 7988 Level: developer 7989 7990 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7991 @*/ 7992 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7993 { 7994 PetscFunctionBegin; 7995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7996 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7997 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7998 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7999 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8000 PetscFunctionReturn(PETSC_SUCCESS); 8001 } 8002 8003 /*@ 8004 MatResidual - Default routine to calculate the residual r = b - Ax 8005 8006 Collective 8007 8008 Input Parameters: 8009 + mat - the matrix 8010 . b - the right-hand-side 8011 - x - the approximate solution 8012 8013 Output Parameter: 8014 . r - location to store the residual 8015 8016 Level: developer 8017 8018 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8019 @*/ 8020 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8021 { 8022 PetscFunctionBegin; 8023 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8024 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8025 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8026 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8027 PetscValidType(mat, 1); 8028 MatCheckPreallocated(mat, 1); 8029 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8030 if (!mat->ops->residual) { 8031 PetscCall(MatMult(mat, x, r)); 8032 PetscCall(VecAYPX(r, -1.0, b)); 8033 } else { 8034 PetscUseTypeMethod(mat, residual, b, x, r); 8035 } 8036 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8037 PetscFunctionReturn(PETSC_SUCCESS); 8038 } 8039 8040 /*@C 8041 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8042 8043 Collective 8044 8045 Input Parameters: 8046 + mat - the matrix 8047 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8048 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8049 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8050 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8051 always used. 8052 8053 Output Parameters: 8054 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8055 . 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 8056 . ja - the column indices, use `NULL` if not needed 8057 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8058 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8059 8060 Level: developer 8061 8062 Notes: 8063 You CANNOT change any of the ia[] or ja[] values. 8064 8065 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8066 8067 Fortran Notes: 8068 Use 8069 .vb 8070 PetscInt, pointer :: ia(:),ja(:) 8071 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8072 ! Access the ith and jth entries via ia(i) and ja(j) 8073 .ve 8074 8075 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8076 @*/ 8077 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8078 { 8079 PetscFunctionBegin; 8080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8081 PetscValidType(mat, 1); 8082 if (n) PetscAssertPointer(n, 5); 8083 if (ia) PetscAssertPointer(ia, 6); 8084 if (ja) PetscAssertPointer(ja, 7); 8085 if (done) PetscAssertPointer(done, 8); 8086 MatCheckPreallocated(mat, 1); 8087 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8088 else { 8089 if (done) *done = PETSC_TRUE; 8090 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8091 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8092 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8093 } 8094 PetscFunctionReturn(PETSC_SUCCESS); 8095 } 8096 8097 /*@C 8098 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8099 8100 Collective 8101 8102 Input Parameters: 8103 + mat - the matrix 8104 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8105 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8106 symmetrized 8107 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8108 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8109 always used. 8110 . n - number of columns in the (possibly compressed) matrix 8111 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8112 - ja - the row indices 8113 8114 Output Parameter: 8115 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8116 8117 Level: developer 8118 8119 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8120 @*/ 8121 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8122 { 8123 PetscFunctionBegin; 8124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8125 PetscValidType(mat, 1); 8126 PetscAssertPointer(n, 5); 8127 if (ia) PetscAssertPointer(ia, 6); 8128 if (ja) PetscAssertPointer(ja, 7); 8129 PetscAssertPointer(done, 8); 8130 MatCheckPreallocated(mat, 1); 8131 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8132 else { 8133 *done = PETSC_TRUE; 8134 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8135 } 8136 PetscFunctionReturn(PETSC_SUCCESS); 8137 } 8138 8139 /*@C 8140 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8141 8142 Collective 8143 8144 Input Parameters: 8145 + mat - the matrix 8146 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8147 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8148 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8149 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8150 always used. 8151 . n - size of (possibly compressed) matrix 8152 . ia - the row pointers 8153 - ja - the column indices 8154 8155 Output Parameter: 8156 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8157 8158 Level: developer 8159 8160 Note: 8161 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8162 us of the array after it has been restored. If you pass `NULL`, it will 8163 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8164 8165 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8166 @*/ 8167 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8168 { 8169 PetscFunctionBegin; 8170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8171 PetscValidType(mat, 1); 8172 if (ia) PetscAssertPointer(ia, 6); 8173 if (ja) PetscAssertPointer(ja, 7); 8174 if (done) PetscAssertPointer(done, 8); 8175 MatCheckPreallocated(mat, 1); 8176 8177 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8178 else { 8179 if (done) *done = PETSC_TRUE; 8180 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8181 if (n) *n = 0; 8182 if (ia) *ia = NULL; 8183 if (ja) *ja = NULL; 8184 } 8185 PetscFunctionReturn(PETSC_SUCCESS); 8186 } 8187 8188 /*@C 8189 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8190 8191 Collective 8192 8193 Input Parameters: 8194 + mat - the matrix 8195 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8196 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8197 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8198 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8199 always used. 8200 8201 Output Parameters: 8202 + n - size of (possibly compressed) matrix 8203 . ia - the column pointers 8204 . ja - the row indices 8205 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8206 8207 Level: developer 8208 8209 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8210 @*/ 8211 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8212 { 8213 PetscFunctionBegin; 8214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8215 PetscValidType(mat, 1); 8216 if (ia) PetscAssertPointer(ia, 6); 8217 if (ja) PetscAssertPointer(ja, 7); 8218 PetscAssertPointer(done, 8); 8219 MatCheckPreallocated(mat, 1); 8220 8221 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8222 else { 8223 *done = PETSC_TRUE; 8224 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8225 if (n) *n = 0; 8226 if (ia) *ia = NULL; 8227 if (ja) *ja = NULL; 8228 } 8229 PetscFunctionReturn(PETSC_SUCCESS); 8230 } 8231 8232 /*@ 8233 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8234 `MatGetColumnIJ()`. 8235 8236 Collective 8237 8238 Input Parameters: 8239 + mat - the matrix 8240 . ncolors - maximum color value 8241 . n - number of entries in colorarray 8242 - colorarray - array indicating color for each column 8243 8244 Output Parameter: 8245 . iscoloring - coloring generated using colorarray information 8246 8247 Level: developer 8248 8249 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8250 @*/ 8251 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8252 { 8253 PetscFunctionBegin; 8254 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8255 PetscValidType(mat, 1); 8256 PetscAssertPointer(colorarray, 4); 8257 PetscAssertPointer(iscoloring, 5); 8258 MatCheckPreallocated(mat, 1); 8259 8260 if (!mat->ops->coloringpatch) { 8261 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8262 } else { 8263 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8264 } 8265 PetscFunctionReturn(PETSC_SUCCESS); 8266 } 8267 8268 /*@ 8269 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8270 8271 Logically Collective 8272 8273 Input Parameter: 8274 . mat - the factored matrix to be reset 8275 8276 Level: developer 8277 8278 Notes: 8279 This routine should be used only with factored matrices formed by in-place 8280 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8281 format). This option can save memory, for example, when solving nonlinear 8282 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8283 ILU(0) preconditioner. 8284 8285 One can specify in-place ILU(0) factorization by calling 8286 .vb 8287 PCType(pc,PCILU); 8288 PCFactorSeUseInPlace(pc); 8289 .ve 8290 or by using the options -pc_type ilu -pc_factor_in_place 8291 8292 In-place factorization ILU(0) can also be used as a local 8293 solver for the blocks within the block Jacobi or additive Schwarz 8294 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8295 for details on setting local solver options. 8296 8297 Most users should employ the `KSP` interface for linear solvers 8298 instead of working directly with matrix algebra routines such as this. 8299 See, e.g., `KSPCreate()`. 8300 8301 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8302 @*/ 8303 PetscErrorCode MatSetUnfactored(Mat mat) 8304 { 8305 PetscFunctionBegin; 8306 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8307 PetscValidType(mat, 1); 8308 MatCheckPreallocated(mat, 1); 8309 mat->factortype = MAT_FACTOR_NONE; 8310 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8311 PetscUseTypeMethod(mat, setunfactored); 8312 PetscFunctionReturn(PETSC_SUCCESS); 8313 } 8314 8315 /*@ 8316 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8317 as the original matrix. 8318 8319 Collective 8320 8321 Input Parameters: 8322 + mat - the original matrix 8323 . isrow - parallel `IS` containing the rows this processor should obtain 8324 . 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. 8325 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8326 8327 Output Parameter: 8328 . newmat - the new submatrix, of the same type as the original matrix 8329 8330 Level: advanced 8331 8332 Notes: 8333 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8334 8335 Some matrix types place restrictions on the row and column indices, such 8336 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; 8337 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8338 8339 The index sets may not have duplicate entries. 8340 8341 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8342 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8343 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8344 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8345 you are finished using it. 8346 8347 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8348 the input matrix. 8349 8350 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8351 8352 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8353 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8354 8355 Example usage: 8356 Consider the following 8x8 matrix with 34 non-zero values, that is 8357 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8358 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8359 as follows 8360 .vb 8361 1 2 0 | 0 3 0 | 0 4 8362 Proc0 0 5 6 | 7 0 0 | 8 0 8363 9 0 10 | 11 0 0 | 12 0 8364 ------------------------------------- 8365 13 0 14 | 15 16 17 | 0 0 8366 Proc1 0 18 0 | 19 20 21 | 0 0 8367 0 0 0 | 22 23 0 | 24 0 8368 ------------------------------------- 8369 Proc2 25 26 27 | 0 0 28 | 29 0 8370 30 0 0 | 31 32 33 | 0 34 8371 .ve 8372 8373 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8374 8375 .vb 8376 2 0 | 0 3 0 | 0 8377 Proc0 5 6 | 7 0 0 | 8 8378 ------------------------------- 8379 Proc1 18 0 | 19 20 21 | 0 8380 ------------------------------- 8381 Proc2 26 27 | 0 0 28 | 29 8382 0 0 | 31 32 33 | 0 8383 .ve 8384 8385 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8386 @*/ 8387 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8388 { 8389 PetscMPIInt size; 8390 Mat *local; 8391 IS iscoltmp; 8392 PetscBool flg; 8393 8394 PetscFunctionBegin; 8395 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8396 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8397 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8398 PetscAssertPointer(newmat, 5); 8399 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8400 PetscValidType(mat, 1); 8401 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8402 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8403 8404 MatCheckPreallocated(mat, 1); 8405 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8406 8407 if (!iscol || isrow == iscol) { 8408 PetscBool stride; 8409 PetscMPIInt grabentirematrix = 0, grab; 8410 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8411 if (stride) { 8412 PetscInt first, step, n, rstart, rend; 8413 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8414 if (step == 1) { 8415 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8416 if (rstart == first) { 8417 PetscCall(ISGetLocalSize(isrow, &n)); 8418 if (n == rend - rstart) grabentirematrix = 1; 8419 } 8420 } 8421 } 8422 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8423 if (grab) { 8424 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8425 if (cll == MAT_INITIAL_MATRIX) { 8426 *newmat = mat; 8427 PetscCall(PetscObjectReference((PetscObject)mat)); 8428 } 8429 PetscFunctionReturn(PETSC_SUCCESS); 8430 } 8431 } 8432 8433 if (!iscol) { 8434 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8435 } else { 8436 iscoltmp = iscol; 8437 } 8438 8439 /* if original matrix is on just one processor then use submatrix generated */ 8440 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8441 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8442 goto setproperties; 8443 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8444 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8445 *newmat = *local; 8446 PetscCall(PetscFree(local)); 8447 goto setproperties; 8448 } else if (!mat->ops->createsubmatrix) { 8449 /* Create a new matrix type that implements the operation using the full matrix */ 8450 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8451 switch (cll) { 8452 case MAT_INITIAL_MATRIX: 8453 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8454 break; 8455 case MAT_REUSE_MATRIX: 8456 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8457 break; 8458 default: 8459 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8460 } 8461 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8462 goto setproperties; 8463 } 8464 8465 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8466 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8467 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8468 8469 setproperties: 8470 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8471 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8472 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8473 } 8474 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8475 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8476 PetscFunctionReturn(PETSC_SUCCESS); 8477 } 8478 8479 /*@ 8480 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8481 8482 Not Collective 8483 8484 Input Parameters: 8485 + A - the matrix we wish to propagate options from 8486 - B - the matrix we wish to propagate options to 8487 8488 Level: beginner 8489 8490 Note: 8491 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8492 8493 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8494 @*/ 8495 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8496 { 8497 PetscFunctionBegin; 8498 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8499 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8500 B->symmetry_eternal = A->symmetry_eternal; 8501 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8502 B->symmetric = A->symmetric; 8503 B->structurally_symmetric = A->structurally_symmetric; 8504 B->spd = A->spd; 8505 B->hermitian = A->hermitian; 8506 PetscFunctionReturn(PETSC_SUCCESS); 8507 } 8508 8509 /*@ 8510 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8511 used during the assembly process to store values that belong to 8512 other processors. 8513 8514 Not Collective 8515 8516 Input Parameters: 8517 + mat - the matrix 8518 . size - the initial size of the stash. 8519 - bsize - the initial size of the block-stash(if used). 8520 8521 Options Database Keys: 8522 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8523 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8524 8525 Level: intermediate 8526 8527 Notes: 8528 The block-stash is used for values set with `MatSetValuesBlocked()` while 8529 the stash is used for values set with `MatSetValues()` 8530 8531 Run with the option -info and look for output of the form 8532 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8533 to determine the appropriate value, MM, to use for size and 8534 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8535 to determine the value, BMM to use for bsize 8536 8537 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8538 @*/ 8539 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8540 { 8541 PetscFunctionBegin; 8542 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8543 PetscValidType(mat, 1); 8544 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8545 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8546 PetscFunctionReturn(PETSC_SUCCESS); 8547 } 8548 8549 /*@ 8550 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8551 the matrix 8552 8553 Neighbor-wise Collective 8554 8555 Input Parameters: 8556 + A - the matrix 8557 . x - the vector to be multiplied by the interpolation operator 8558 - y - the vector to be added to the result 8559 8560 Output Parameter: 8561 . w - the resulting vector 8562 8563 Level: intermediate 8564 8565 Notes: 8566 `w` may be the same vector as `y`. 8567 8568 This allows one to use either the restriction or interpolation (its transpose) 8569 matrix to do the interpolation 8570 8571 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8572 @*/ 8573 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8574 { 8575 PetscInt M, N, Ny; 8576 8577 PetscFunctionBegin; 8578 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8579 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8580 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8581 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8582 PetscCall(MatGetSize(A, &M, &N)); 8583 PetscCall(VecGetSize(y, &Ny)); 8584 if (M == Ny) { 8585 PetscCall(MatMultAdd(A, x, y, w)); 8586 } else { 8587 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8588 } 8589 PetscFunctionReturn(PETSC_SUCCESS); 8590 } 8591 8592 /*@ 8593 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8594 the matrix 8595 8596 Neighbor-wise Collective 8597 8598 Input Parameters: 8599 + A - the matrix 8600 - x - the vector to be interpolated 8601 8602 Output Parameter: 8603 . y - the resulting vector 8604 8605 Level: intermediate 8606 8607 Note: 8608 This allows one to use either the restriction or interpolation (its transpose) 8609 matrix to do the interpolation 8610 8611 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8612 @*/ 8613 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8614 { 8615 PetscInt M, N, Ny; 8616 8617 PetscFunctionBegin; 8618 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8619 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8620 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8621 PetscCall(MatGetSize(A, &M, &N)); 8622 PetscCall(VecGetSize(y, &Ny)); 8623 if (M == Ny) { 8624 PetscCall(MatMult(A, x, y)); 8625 } else { 8626 PetscCall(MatMultTranspose(A, x, y)); 8627 } 8628 PetscFunctionReturn(PETSC_SUCCESS); 8629 } 8630 8631 /*@ 8632 MatRestrict - $y = A*x$ or $A^T*x$ 8633 8634 Neighbor-wise Collective 8635 8636 Input Parameters: 8637 + A - the matrix 8638 - x - the vector to be restricted 8639 8640 Output Parameter: 8641 . y - the resulting vector 8642 8643 Level: intermediate 8644 8645 Note: 8646 This allows one to use either the restriction or interpolation (its transpose) 8647 matrix to do the restriction 8648 8649 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8650 @*/ 8651 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8652 { 8653 PetscInt M, N, Nx; 8654 8655 PetscFunctionBegin; 8656 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8657 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8658 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8659 PetscCall(MatGetSize(A, &M, &N)); 8660 PetscCall(VecGetSize(x, &Nx)); 8661 if (M == Nx) { 8662 PetscCall(MatMultTranspose(A, x, y)); 8663 } else { 8664 PetscCall(MatMult(A, x, y)); 8665 } 8666 PetscFunctionReturn(PETSC_SUCCESS); 8667 } 8668 8669 /*@ 8670 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8671 8672 Neighbor-wise Collective 8673 8674 Input Parameters: 8675 + A - the matrix 8676 . x - the input dense matrix to be multiplied 8677 - w - the input dense matrix to be added to the result 8678 8679 Output Parameter: 8680 . y - the output dense matrix 8681 8682 Level: intermediate 8683 8684 Note: 8685 This allows one to use either the restriction or interpolation (its transpose) 8686 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8687 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8688 8689 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8690 @*/ 8691 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8692 { 8693 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8694 PetscBool trans = PETSC_TRUE; 8695 MatReuse reuse = MAT_INITIAL_MATRIX; 8696 8697 PetscFunctionBegin; 8698 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8699 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8700 PetscValidType(x, 2); 8701 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8702 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8703 PetscCall(MatGetSize(A, &M, &N)); 8704 PetscCall(MatGetSize(x, &Mx, &Nx)); 8705 if (N == Mx) trans = PETSC_FALSE; 8706 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); 8707 Mo = trans ? N : M; 8708 if (*y) { 8709 PetscCall(MatGetSize(*y, &My, &Ny)); 8710 if (Mo == My && Nx == Ny) { 8711 reuse = MAT_REUSE_MATRIX; 8712 } else { 8713 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); 8714 PetscCall(MatDestroy(y)); 8715 } 8716 } 8717 8718 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8719 PetscBool flg; 8720 8721 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8722 if (w) { 8723 PetscInt My, Ny, Mw, Nw; 8724 8725 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8726 PetscCall(MatGetSize(*y, &My, &Ny)); 8727 PetscCall(MatGetSize(w, &Mw, &Nw)); 8728 if (!flg || My != Mw || Ny != Nw) w = NULL; 8729 } 8730 if (!w) { 8731 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8732 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8733 PetscCall(PetscObjectDereference((PetscObject)w)); 8734 } else { 8735 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8736 } 8737 } 8738 if (!trans) { 8739 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8740 } else { 8741 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8742 } 8743 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8744 PetscFunctionReturn(PETSC_SUCCESS); 8745 } 8746 8747 /*@ 8748 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8749 8750 Neighbor-wise Collective 8751 8752 Input Parameters: 8753 + A - the matrix 8754 - x - the input dense matrix 8755 8756 Output Parameter: 8757 . y - the output dense matrix 8758 8759 Level: intermediate 8760 8761 Note: 8762 This allows one to use either the restriction or interpolation (its transpose) 8763 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8764 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8765 8766 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8767 @*/ 8768 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8769 { 8770 PetscFunctionBegin; 8771 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8772 PetscFunctionReturn(PETSC_SUCCESS); 8773 } 8774 8775 /*@ 8776 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8777 8778 Neighbor-wise Collective 8779 8780 Input Parameters: 8781 + A - the matrix 8782 - x - the input dense matrix 8783 8784 Output Parameter: 8785 . y - the output dense matrix 8786 8787 Level: intermediate 8788 8789 Note: 8790 This allows one to use either the restriction or interpolation (its transpose) 8791 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8792 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8793 8794 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8795 @*/ 8796 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8797 { 8798 PetscFunctionBegin; 8799 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8800 PetscFunctionReturn(PETSC_SUCCESS); 8801 } 8802 8803 /*@ 8804 MatGetNullSpace - retrieves the null space of a matrix. 8805 8806 Logically Collective 8807 8808 Input Parameters: 8809 + mat - the matrix 8810 - nullsp - the null space object 8811 8812 Level: developer 8813 8814 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8815 @*/ 8816 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8817 { 8818 PetscFunctionBegin; 8819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8820 PetscAssertPointer(nullsp, 2); 8821 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8822 PetscFunctionReturn(PETSC_SUCCESS); 8823 } 8824 8825 /*@C 8826 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8827 8828 Logically Collective 8829 8830 Input Parameters: 8831 + n - the number of matrices 8832 - mat - the array of matrices 8833 8834 Output Parameters: 8835 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8836 8837 Level: developer 8838 8839 Note: 8840 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8841 8842 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8843 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8844 @*/ 8845 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8846 { 8847 PetscFunctionBegin; 8848 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8849 PetscAssertPointer(mat, 2); 8850 PetscAssertPointer(nullsp, 3); 8851 8852 PetscCall(PetscCalloc1(3 * n, nullsp)); 8853 for (PetscInt i = 0; i < n; i++) { 8854 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8855 (*nullsp)[i] = mat[i]->nullsp; 8856 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8857 (*nullsp)[n + i] = mat[i]->nearnullsp; 8858 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8859 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8860 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8861 } 8862 PetscFunctionReturn(PETSC_SUCCESS); 8863 } 8864 8865 /*@C 8866 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8867 8868 Logically Collective 8869 8870 Input Parameters: 8871 + n - the number of matrices 8872 . mat - the array of matrices 8873 - nullsp - an array of null spaces 8874 8875 Level: developer 8876 8877 Note: 8878 Call `MatGetNullSpaces()` to create `nullsp` 8879 8880 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8881 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8882 @*/ 8883 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8884 { 8885 PetscFunctionBegin; 8886 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8887 PetscAssertPointer(mat, 2); 8888 PetscAssertPointer(nullsp, 3); 8889 PetscAssertPointer(*nullsp, 3); 8890 8891 for (PetscInt i = 0; i < n; i++) { 8892 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8893 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8894 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8895 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8896 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8897 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8898 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8899 } 8900 PetscCall(PetscFree(*nullsp)); 8901 PetscFunctionReturn(PETSC_SUCCESS); 8902 } 8903 8904 /*@ 8905 MatSetNullSpace - attaches a null space to a matrix. 8906 8907 Logically Collective 8908 8909 Input Parameters: 8910 + mat - the matrix 8911 - nullsp - the null space object 8912 8913 Level: advanced 8914 8915 Notes: 8916 This null space is used by the `KSP` linear solvers to solve singular systems. 8917 8918 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` 8919 8920 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 8921 to zero but the linear system will still be solved in a least squares sense. 8922 8923 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8924 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)$. 8925 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 8926 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 8927 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$). 8928 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8929 8930 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8931 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8932 routine also automatically calls `MatSetTransposeNullSpace()`. 8933 8934 The user should call `MatNullSpaceDestroy()`. 8935 8936 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8937 `KSPSetPCSide()` 8938 @*/ 8939 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8940 { 8941 PetscFunctionBegin; 8942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8943 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8944 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8945 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8946 mat->nullsp = nullsp; 8947 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8948 PetscFunctionReturn(PETSC_SUCCESS); 8949 } 8950 8951 /*@ 8952 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8953 8954 Logically Collective 8955 8956 Input Parameters: 8957 + mat - the matrix 8958 - nullsp - the null space object 8959 8960 Level: developer 8961 8962 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8963 @*/ 8964 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8965 { 8966 PetscFunctionBegin; 8967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8968 PetscValidType(mat, 1); 8969 PetscAssertPointer(nullsp, 2); 8970 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8971 PetscFunctionReturn(PETSC_SUCCESS); 8972 } 8973 8974 /*@ 8975 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8976 8977 Logically Collective 8978 8979 Input Parameters: 8980 + mat - the matrix 8981 - nullsp - the null space object 8982 8983 Level: advanced 8984 8985 Notes: 8986 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8987 8988 See `MatSetNullSpace()` 8989 8990 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8991 @*/ 8992 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8993 { 8994 PetscFunctionBegin; 8995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8996 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8997 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8998 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8999 mat->transnullsp = nullsp; 9000 PetscFunctionReturn(PETSC_SUCCESS); 9001 } 9002 9003 /*@ 9004 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9005 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9006 9007 Logically Collective 9008 9009 Input Parameters: 9010 + mat - the matrix 9011 - nullsp - the null space object 9012 9013 Level: advanced 9014 9015 Notes: 9016 Overwrites any previous near null space that may have been attached 9017 9018 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9019 9020 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9021 @*/ 9022 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9023 { 9024 PetscFunctionBegin; 9025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9026 PetscValidType(mat, 1); 9027 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9028 MatCheckPreallocated(mat, 1); 9029 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9030 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9031 mat->nearnullsp = nullsp; 9032 PetscFunctionReturn(PETSC_SUCCESS); 9033 } 9034 9035 /*@ 9036 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9037 9038 Not Collective 9039 9040 Input Parameter: 9041 . mat - the matrix 9042 9043 Output Parameter: 9044 . nullsp - the null space object, `NULL` if not set 9045 9046 Level: advanced 9047 9048 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9049 @*/ 9050 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9051 { 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9054 PetscValidType(mat, 1); 9055 PetscAssertPointer(nullsp, 2); 9056 MatCheckPreallocated(mat, 1); 9057 *nullsp = mat->nearnullsp; 9058 PetscFunctionReturn(PETSC_SUCCESS); 9059 } 9060 9061 /*@ 9062 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9063 9064 Collective 9065 9066 Input Parameters: 9067 + mat - the matrix 9068 . row - row/column permutation 9069 - info - information on desired factorization process 9070 9071 Level: developer 9072 9073 Notes: 9074 Probably really in-place only when level of fill is zero, otherwise allocates 9075 new space to store factored matrix and deletes previous memory. 9076 9077 Most users should employ the `KSP` interface for linear solvers 9078 instead of working directly with matrix algebra routines such as this. 9079 See, e.g., `KSPCreate()`. 9080 9081 Fortran Note: 9082 A valid (non-null) `info` argument must be provided 9083 9084 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9085 @*/ 9086 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9087 { 9088 PetscFunctionBegin; 9089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9090 PetscValidType(mat, 1); 9091 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9092 PetscAssertPointer(info, 3); 9093 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9094 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9095 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9096 MatCheckPreallocated(mat, 1); 9097 PetscUseTypeMethod(mat, iccfactor, row, info); 9098 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9099 PetscFunctionReturn(PETSC_SUCCESS); 9100 } 9101 9102 /*@ 9103 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9104 ghosted ones. 9105 9106 Not Collective 9107 9108 Input Parameters: 9109 + mat - the matrix 9110 - diag - the diagonal values, including ghost ones 9111 9112 Level: developer 9113 9114 Notes: 9115 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9116 9117 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9118 9119 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9120 @*/ 9121 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9122 { 9123 PetscMPIInt size; 9124 9125 PetscFunctionBegin; 9126 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9127 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9128 PetscValidType(mat, 1); 9129 9130 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9131 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9132 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9133 if (size == 1) { 9134 PetscInt n, m; 9135 PetscCall(VecGetSize(diag, &n)); 9136 PetscCall(MatGetSize(mat, NULL, &m)); 9137 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9138 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9139 } else { 9140 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9141 } 9142 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9143 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9144 PetscFunctionReturn(PETSC_SUCCESS); 9145 } 9146 9147 /*@ 9148 MatGetInertia - Gets the inertia from a factored matrix 9149 9150 Collective 9151 9152 Input Parameter: 9153 . mat - the matrix 9154 9155 Output Parameters: 9156 + nneg - number of negative eigenvalues 9157 . nzero - number of zero eigenvalues 9158 - npos - number of positive eigenvalues 9159 9160 Level: advanced 9161 9162 Note: 9163 Matrix must have been factored by `MatCholeskyFactor()` 9164 9165 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9166 @*/ 9167 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9168 { 9169 PetscFunctionBegin; 9170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9171 PetscValidType(mat, 1); 9172 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9173 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9174 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9175 PetscFunctionReturn(PETSC_SUCCESS); 9176 } 9177 9178 /*@C 9179 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9180 9181 Neighbor-wise Collective 9182 9183 Input Parameters: 9184 + mat - the factored matrix obtained with `MatGetFactor()` 9185 - b - the right-hand-side vectors 9186 9187 Output Parameter: 9188 . x - the result vectors 9189 9190 Level: developer 9191 9192 Note: 9193 The vectors `b` and `x` cannot be the same. I.e., one cannot 9194 call `MatSolves`(A,x,x). 9195 9196 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9197 @*/ 9198 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9199 { 9200 PetscFunctionBegin; 9201 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9202 PetscValidType(mat, 1); 9203 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9204 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9205 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9206 9207 MatCheckPreallocated(mat, 1); 9208 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9209 PetscUseTypeMethod(mat, solves, b, x); 9210 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9211 PetscFunctionReturn(PETSC_SUCCESS); 9212 } 9213 9214 /*@ 9215 MatIsSymmetric - Test whether a matrix is symmetric 9216 9217 Collective 9218 9219 Input Parameters: 9220 + A - the matrix to test 9221 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9222 9223 Output Parameter: 9224 . flg - the result 9225 9226 Level: intermediate 9227 9228 Notes: 9229 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9230 9231 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9232 9233 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9234 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9235 9236 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9237 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9238 @*/ 9239 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9240 { 9241 PetscFunctionBegin; 9242 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9243 PetscAssertPointer(flg, 3); 9244 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9245 else { 9246 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9247 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9248 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9249 } 9250 PetscFunctionReturn(PETSC_SUCCESS); 9251 } 9252 9253 /*@ 9254 MatIsHermitian - Test whether a matrix is Hermitian 9255 9256 Collective 9257 9258 Input Parameters: 9259 + A - the matrix to test 9260 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9261 9262 Output Parameter: 9263 . flg - the result 9264 9265 Level: intermediate 9266 9267 Notes: 9268 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9269 9270 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9271 9272 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9273 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9274 9275 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9276 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9277 @*/ 9278 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9279 { 9280 PetscFunctionBegin; 9281 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9282 PetscAssertPointer(flg, 3); 9283 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9284 else { 9285 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9286 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9287 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9288 } 9289 PetscFunctionReturn(PETSC_SUCCESS); 9290 } 9291 9292 /*@ 9293 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9294 9295 Not Collective 9296 9297 Input Parameter: 9298 . A - the matrix to check 9299 9300 Output Parameters: 9301 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9302 - flg - the result (only valid if set is `PETSC_TRUE`) 9303 9304 Level: advanced 9305 9306 Notes: 9307 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9308 if you want it explicitly checked 9309 9310 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9311 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9312 9313 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9314 @*/ 9315 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9316 { 9317 PetscFunctionBegin; 9318 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9319 PetscAssertPointer(set, 2); 9320 PetscAssertPointer(flg, 3); 9321 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9322 *set = PETSC_TRUE; 9323 *flg = PetscBool3ToBool(A->symmetric); 9324 } else { 9325 *set = PETSC_FALSE; 9326 } 9327 PetscFunctionReturn(PETSC_SUCCESS); 9328 } 9329 9330 /*@ 9331 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9332 9333 Not Collective 9334 9335 Input Parameter: 9336 . A - the matrix to check 9337 9338 Output Parameters: 9339 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9340 - flg - the result (only valid if set is `PETSC_TRUE`) 9341 9342 Level: advanced 9343 9344 Notes: 9345 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9346 9347 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9348 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9349 9350 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9351 @*/ 9352 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9353 { 9354 PetscFunctionBegin; 9355 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9356 PetscAssertPointer(set, 2); 9357 PetscAssertPointer(flg, 3); 9358 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9359 *set = PETSC_TRUE; 9360 *flg = PetscBool3ToBool(A->spd); 9361 } else { 9362 *set = PETSC_FALSE; 9363 } 9364 PetscFunctionReturn(PETSC_SUCCESS); 9365 } 9366 9367 /*@ 9368 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9369 9370 Not Collective 9371 9372 Input Parameter: 9373 . A - the matrix to check 9374 9375 Output Parameters: 9376 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9377 - flg - the result (only valid if set is `PETSC_TRUE`) 9378 9379 Level: advanced 9380 9381 Notes: 9382 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9383 if you want it explicitly checked 9384 9385 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9386 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9387 9388 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9389 @*/ 9390 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9391 { 9392 PetscFunctionBegin; 9393 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9394 PetscAssertPointer(set, 2); 9395 PetscAssertPointer(flg, 3); 9396 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9397 *set = PETSC_TRUE; 9398 *flg = PetscBool3ToBool(A->hermitian); 9399 } else { 9400 *set = PETSC_FALSE; 9401 } 9402 PetscFunctionReturn(PETSC_SUCCESS); 9403 } 9404 9405 /*@ 9406 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9407 9408 Collective 9409 9410 Input Parameter: 9411 . A - the matrix to test 9412 9413 Output Parameter: 9414 . flg - the result 9415 9416 Level: intermediate 9417 9418 Notes: 9419 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9420 9421 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 9422 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9423 9424 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9425 @*/ 9426 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9427 { 9428 PetscFunctionBegin; 9429 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9430 PetscAssertPointer(flg, 2); 9431 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9432 *flg = PetscBool3ToBool(A->structurally_symmetric); 9433 } else { 9434 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9435 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9436 } 9437 PetscFunctionReturn(PETSC_SUCCESS); 9438 } 9439 9440 /*@ 9441 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9442 9443 Not Collective 9444 9445 Input Parameter: 9446 . A - the matrix to check 9447 9448 Output Parameters: 9449 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9450 - flg - the result (only valid if set is PETSC_TRUE) 9451 9452 Level: advanced 9453 9454 Notes: 9455 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 9456 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9457 9458 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9459 9460 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9461 @*/ 9462 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9463 { 9464 PetscFunctionBegin; 9465 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9466 PetscAssertPointer(set, 2); 9467 PetscAssertPointer(flg, 3); 9468 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9469 *set = PETSC_TRUE; 9470 *flg = PetscBool3ToBool(A->structurally_symmetric); 9471 } else { 9472 *set = PETSC_FALSE; 9473 } 9474 PetscFunctionReturn(PETSC_SUCCESS); 9475 } 9476 9477 /*@ 9478 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9479 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9480 9481 Not Collective 9482 9483 Input Parameter: 9484 . mat - the matrix 9485 9486 Output Parameters: 9487 + nstash - the size of the stash 9488 . reallocs - the number of additional mallocs incurred. 9489 . bnstash - the size of the block stash 9490 - breallocs - the number of additional mallocs incurred.in the block stash 9491 9492 Level: advanced 9493 9494 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9495 @*/ 9496 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9497 { 9498 PetscFunctionBegin; 9499 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9500 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9501 PetscFunctionReturn(PETSC_SUCCESS); 9502 } 9503 9504 /*@ 9505 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9506 parallel layout, `PetscLayout` for rows and columns 9507 9508 Collective 9509 9510 Input Parameter: 9511 . mat - the matrix 9512 9513 Output Parameters: 9514 + right - (optional) vector that the matrix can be multiplied against 9515 - left - (optional) vector that the matrix vector product can be stored in 9516 9517 Level: advanced 9518 9519 Notes: 9520 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()`. 9521 9522 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9523 9524 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9525 @*/ 9526 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9527 { 9528 PetscFunctionBegin; 9529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9530 PetscValidType(mat, 1); 9531 if (mat->ops->getvecs) { 9532 PetscUseTypeMethod(mat, getvecs, right, left); 9533 } else { 9534 if (right) { 9535 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9536 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9537 PetscCall(VecSetType(*right, mat->defaultvectype)); 9538 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9539 if (mat->boundtocpu && mat->bindingpropagates) { 9540 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9541 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9542 } 9543 #endif 9544 } 9545 if (left) { 9546 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9547 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9548 PetscCall(VecSetType(*left, mat->defaultvectype)); 9549 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9550 if (mat->boundtocpu && mat->bindingpropagates) { 9551 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9552 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9553 } 9554 #endif 9555 } 9556 } 9557 PetscFunctionReturn(PETSC_SUCCESS); 9558 } 9559 9560 /*@ 9561 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9562 with default values. 9563 9564 Not Collective 9565 9566 Input Parameter: 9567 . info - the `MatFactorInfo` data structure 9568 9569 Level: developer 9570 9571 Notes: 9572 The solvers are generally used through the `KSP` and `PC` objects, for example 9573 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9574 9575 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9576 9577 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9578 @*/ 9579 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9580 { 9581 PetscFunctionBegin; 9582 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9583 PetscFunctionReturn(PETSC_SUCCESS); 9584 } 9585 9586 /*@ 9587 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9588 9589 Collective 9590 9591 Input Parameters: 9592 + mat - the factored matrix 9593 - is - the index set defining the Schur indices (0-based) 9594 9595 Level: advanced 9596 9597 Notes: 9598 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9599 9600 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9601 9602 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9603 9604 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9605 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9606 @*/ 9607 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9608 { 9609 PetscErrorCode (*f)(Mat, IS); 9610 9611 PetscFunctionBegin; 9612 PetscValidType(mat, 1); 9613 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9614 PetscValidType(is, 2); 9615 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9616 PetscCheckSameComm(mat, 1, is, 2); 9617 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9618 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9619 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9620 PetscCall(MatDestroy(&mat->schur)); 9621 PetscCall((*f)(mat, is)); 9622 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9623 PetscFunctionReturn(PETSC_SUCCESS); 9624 } 9625 9626 /*@ 9627 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9628 9629 Logically Collective 9630 9631 Input Parameters: 9632 + F - the factored matrix obtained by calling `MatGetFactor()` 9633 . S - location where to return the Schur complement, can be `NULL` 9634 - status - the status of the Schur complement matrix, can be `NULL` 9635 9636 Level: advanced 9637 9638 Notes: 9639 You must call `MatFactorSetSchurIS()` before calling this routine. 9640 9641 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9642 9643 The routine provides a copy of the Schur matrix stored within the solver data structures. 9644 The caller must destroy the object when it is no longer needed. 9645 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9646 9647 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) 9648 9649 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9650 9651 Developer Note: 9652 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9653 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9654 9655 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9656 @*/ 9657 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9658 { 9659 PetscFunctionBegin; 9660 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9661 if (S) PetscAssertPointer(S, 2); 9662 if (status) PetscAssertPointer(status, 3); 9663 if (S) { 9664 PetscErrorCode (*f)(Mat, Mat *); 9665 9666 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9667 if (f) { 9668 PetscCall((*f)(F, S)); 9669 } else { 9670 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9671 } 9672 } 9673 if (status) *status = F->schur_status; 9674 PetscFunctionReturn(PETSC_SUCCESS); 9675 } 9676 9677 /*@ 9678 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9679 9680 Logically Collective 9681 9682 Input Parameters: 9683 + F - the factored matrix obtained by calling `MatGetFactor()` 9684 . S - location where to return the Schur complement, can be `NULL` 9685 - status - the status of the Schur complement matrix, can be `NULL` 9686 9687 Level: advanced 9688 9689 Notes: 9690 You must call `MatFactorSetSchurIS()` before calling this routine. 9691 9692 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9693 9694 The routine returns a the Schur Complement stored within the data structures of the solver. 9695 9696 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9697 9698 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9699 9700 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9701 9702 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9703 9704 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9705 @*/ 9706 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9707 { 9708 PetscFunctionBegin; 9709 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9710 if (S) { 9711 PetscAssertPointer(S, 2); 9712 *S = F->schur; 9713 } 9714 if (status) { 9715 PetscAssertPointer(status, 3); 9716 *status = F->schur_status; 9717 } 9718 PetscFunctionReturn(PETSC_SUCCESS); 9719 } 9720 9721 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9722 { 9723 Mat S = F->schur; 9724 9725 PetscFunctionBegin; 9726 switch (F->schur_status) { 9727 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9728 case MAT_FACTOR_SCHUR_INVERTED: 9729 if (S) { 9730 S->ops->solve = NULL; 9731 S->ops->matsolve = NULL; 9732 S->ops->solvetranspose = NULL; 9733 S->ops->matsolvetranspose = NULL; 9734 S->ops->solveadd = NULL; 9735 S->ops->solvetransposeadd = NULL; 9736 S->factortype = MAT_FACTOR_NONE; 9737 PetscCall(PetscFree(S->solvertype)); 9738 } 9739 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9740 break; 9741 default: 9742 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9743 } 9744 PetscFunctionReturn(PETSC_SUCCESS); 9745 } 9746 9747 /*@ 9748 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9749 9750 Logically Collective 9751 9752 Input Parameters: 9753 + F - the factored matrix obtained by calling `MatGetFactor()` 9754 . S - location where the Schur complement is stored 9755 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9756 9757 Level: advanced 9758 9759 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9760 @*/ 9761 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9762 { 9763 PetscFunctionBegin; 9764 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9765 if (S) { 9766 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9767 *S = NULL; 9768 } 9769 F->schur_status = status; 9770 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9771 PetscFunctionReturn(PETSC_SUCCESS); 9772 } 9773 9774 /*@ 9775 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9776 9777 Logically Collective 9778 9779 Input Parameters: 9780 + F - the factored matrix obtained by calling `MatGetFactor()` 9781 . rhs - location where the right-hand side of the Schur complement system is stored 9782 - sol - location where the solution of the Schur complement system has to be returned 9783 9784 Level: advanced 9785 9786 Notes: 9787 The sizes of the vectors should match the size of the Schur complement 9788 9789 Must be called after `MatFactorSetSchurIS()` 9790 9791 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9792 @*/ 9793 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9794 { 9795 PetscFunctionBegin; 9796 PetscValidType(F, 1); 9797 PetscValidType(rhs, 2); 9798 PetscValidType(sol, 3); 9799 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9800 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9801 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9802 PetscCheckSameComm(F, 1, rhs, 2); 9803 PetscCheckSameComm(F, 1, sol, 3); 9804 PetscCall(MatFactorFactorizeSchurComplement(F)); 9805 switch (F->schur_status) { 9806 case MAT_FACTOR_SCHUR_FACTORED: 9807 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9808 break; 9809 case MAT_FACTOR_SCHUR_INVERTED: 9810 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9811 break; 9812 default: 9813 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9814 } 9815 PetscFunctionReturn(PETSC_SUCCESS); 9816 } 9817 9818 /*@ 9819 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9820 9821 Logically Collective 9822 9823 Input Parameters: 9824 + F - the factored matrix obtained by calling `MatGetFactor()` 9825 . rhs - location where the right-hand side of the Schur complement system is stored 9826 - sol - location where the solution of the Schur complement system has to be returned 9827 9828 Level: advanced 9829 9830 Notes: 9831 The sizes of the vectors should match the size of the Schur complement 9832 9833 Must be called after `MatFactorSetSchurIS()` 9834 9835 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9836 @*/ 9837 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9838 { 9839 PetscFunctionBegin; 9840 PetscValidType(F, 1); 9841 PetscValidType(rhs, 2); 9842 PetscValidType(sol, 3); 9843 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9844 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9845 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9846 PetscCheckSameComm(F, 1, rhs, 2); 9847 PetscCheckSameComm(F, 1, sol, 3); 9848 PetscCall(MatFactorFactorizeSchurComplement(F)); 9849 switch (F->schur_status) { 9850 case MAT_FACTOR_SCHUR_FACTORED: 9851 PetscCall(MatSolve(F->schur, rhs, sol)); 9852 break; 9853 case MAT_FACTOR_SCHUR_INVERTED: 9854 PetscCall(MatMult(F->schur, rhs, sol)); 9855 break; 9856 default: 9857 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9858 } 9859 PetscFunctionReturn(PETSC_SUCCESS); 9860 } 9861 9862 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9863 #if PetscDefined(HAVE_CUDA) 9864 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9865 #endif 9866 9867 /* Schur status updated in the interface */ 9868 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9869 { 9870 Mat S = F->schur; 9871 9872 PetscFunctionBegin; 9873 if (S) { 9874 PetscMPIInt size; 9875 PetscBool isdense, isdensecuda; 9876 9877 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9878 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9879 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9880 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9881 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9882 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9883 if (isdense) { 9884 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9885 } else if (isdensecuda) { 9886 #if defined(PETSC_HAVE_CUDA) 9887 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9888 #endif 9889 } 9890 // HIP?????????????? 9891 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9892 } 9893 PetscFunctionReturn(PETSC_SUCCESS); 9894 } 9895 9896 /*@ 9897 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9898 9899 Logically Collective 9900 9901 Input Parameter: 9902 . F - the factored matrix obtained by calling `MatGetFactor()` 9903 9904 Level: advanced 9905 9906 Notes: 9907 Must be called after `MatFactorSetSchurIS()`. 9908 9909 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9910 9911 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9912 @*/ 9913 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9914 { 9915 PetscFunctionBegin; 9916 PetscValidType(F, 1); 9917 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9918 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9919 PetscCall(MatFactorFactorizeSchurComplement(F)); 9920 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9921 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9922 PetscFunctionReturn(PETSC_SUCCESS); 9923 } 9924 9925 /*@ 9926 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9927 9928 Logically Collective 9929 9930 Input Parameter: 9931 . F - the factored matrix obtained by calling `MatGetFactor()` 9932 9933 Level: advanced 9934 9935 Note: 9936 Must be called after `MatFactorSetSchurIS()` 9937 9938 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9939 @*/ 9940 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9941 { 9942 MatFactorInfo info; 9943 9944 PetscFunctionBegin; 9945 PetscValidType(F, 1); 9946 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9947 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9948 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9949 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9950 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9951 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9952 } else { 9953 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9954 } 9955 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9956 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9957 PetscFunctionReturn(PETSC_SUCCESS); 9958 } 9959 9960 /*@ 9961 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9962 9963 Neighbor-wise Collective 9964 9965 Input Parameters: 9966 + A - the matrix 9967 . P - the projection matrix 9968 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9969 - 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 9970 if the result is a dense matrix this is irrelevant 9971 9972 Output Parameter: 9973 . C - the product matrix 9974 9975 Level: intermediate 9976 9977 Notes: 9978 C will be created and must be destroyed by the user with `MatDestroy()`. 9979 9980 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9981 9982 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 9983 9984 Developer Note: 9985 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9986 9987 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9988 @*/ 9989 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9990 { 9991 PetscFunctionBegin; 9992 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9993 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9994 9995 if (scall == MAT_INITIAL_MATRIX) { 9996 PetscCall(MatProductCreate(A, P, NULL, C)); 9997 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9998 PetscCall(MatProductSetAlgorithm(*C, "default")); 9999 PetscCall(MatProductSetFill(*C, fill)); 10000 10001 (*C)->product->api_user = PETSC_TRUE; 10002 PetscCall(MatProductSetFromOptions(*C)); 10003 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); 10004 PetscCall(MatProductSymbolic(*C)); 10005 } else { /* scall == MAT_REUSE_MATRIX */ 10006 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10007 } 10008 10009 PetscCall(MatProductNumeric(*C)); 10010 (*C)->symmetric = A->symmetric; 10011 (*C)->spd = A->spd; 10012 PetscFunctionReturn(PETSC_SUCCESS); 10013 } 10014 10015 /*@ 10016 MatRARt - Creates the matrix product $C = R * A * R^T$ 10017 10018 Neighbor-wise Collective 10019 10020 Input Parameters: 10021 + A - the matrix 10022 . R - the projection matrix 10023 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10024 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10025 if the result is a dense matrix this is irrelevant 10026 10027 Output Parameter: 10028 . C - the product matrix 10029 10030 Level: intermediate 10031 10032 Notes: 10033 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10034 10035 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10036 10037 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10038 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10039 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10040 We recommend using `MatPtAP()` when possible. 10041 10042 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10043 10044 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10045 @*/ 10046 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10047 { 10048 PetscFunctionBegin; 10049 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10050 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10051 10052 if (scall == MAT_INITIAL_MATRIX) { 10053 PetscCall(MatProductCreate(A, R, NULL, C)); 10054 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10055 PetscCall(MatProductSetAlgorithm(*C, "default")); 10056 PetscCall(MatProductSetFill(*C, fill)); 10057 10058 (*C)->product->api_user = PETSC_TRUE; 10059 PetscCall(MatProductSetFromOptions(*C)); 10060 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); 10061 PetscCall(MatProductSymbolic(*C)); 10062 } else { /* scall == MAT_REUSE_MATRIX */ 10063 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10064 } 10065 10066 PetscCall(MatProductNumeric(*C)); 10067 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10068 PetscFunctionReturn(PETSC_SUCCESS); 10069 } 10070 10071 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10072 { 10073 PetscBool flg = PETSC_TRUE; 10074 10075 PetscFunctionBegin; 10076 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10077 if (scall == MAT_INITIAL_MATRIX) { 10078 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10079 PetscCall(MatProductCreate(A, B, NULL, C)); 10080 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10081 PetscCall(MatProductSetFill(*C, fill)); 10082 } else { /* scall == MAT_REUSE_MATRIX */ 10083 Mat_Product *product = (*C)->product; 10084 10085 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10086 if (flg && product && product->type != ptype) { 10087 PetscCall(MatProductClear(*C)); 10088 product = NULL; 10089 } 10090 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10091 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10092 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10093 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10094 product = (*C)->product; 10095 product->fill = fill; 10096 product->clear = PETSC_TRUE; 10097 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10098 flg = PETSC_FALSE; 10099 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10100 } 10101 } 10102 if (flg) { 10103 (*C)->product->api_user = PETSC_TRUE; 10104 PetscCall(MatProductSetType(*C, ptype)); 10105 PetscCall(MatProductSetFromOptions(*C)); 10106 PetscCall(MatProductSymbolic(*C)); 10107 } 10108 PetscCall(MatProductNumeric(*C)); 10109 PetscFunctionReturn(PETSC_SUCCESS); 10110 } 10111 10112 /*@ 10113 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10114 10115 Neighbor-wise Collective 10116 10117 Input Parameters: 10118 + A - the left matrix 10119 . B - the right matrix 10120 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10121 - 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 10122 if the result is a dense matrix this is irrelevant 10123 10124 Output Parameter: 10125 . C - the product matrix 10126 10127 Notes: 10128 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10129 10130 `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 10131 call to this function with `MAT_INITIAL_MATRIX`. 10132 10133 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10134 10135 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`, 10136 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10137 10138 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10139 10140 Example of Usage: 10141 .vb 10142 MatProductCreate(A,B,NULL,&C); 10143 MatProductSetType(C,MATPRODUCT_AB); 10144 MatProductSymbolic(C); 10145 MatProductNumeric(C); // compute C=A * B 10146 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10147 MatProductNumeric(C); 10148 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10149 MatProductNumeric(C); 10150 .ve 10151 10152 Level: intermediate 10153 10154 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10155 @*/ 10156 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10157 { 10158 PetscFunctionBegin; 10159 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10160 PetscFunctionReturn(PETSC_SUCCESS); 10161 } 10162 10163 /*@ 10164 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10165 10166 Neighbor-wise Collective 10167 10168 Input Parameters: 10169 + A - the left matrix 10170 . B - the right matrix 10171 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10172 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10173 10174 Output Parameter: 10175 . C - the product matrix 10176 10177 Options Database Key: 10178 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10179 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10180 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10181 10182 Level: intermediate 10183 10184 Notes: 10185 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10186 10187 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10188 10189 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10190 actually needed. 10191 10192 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10193 and for pairs of `MATMPIDENSE` matrices. 10194 10195 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10196 10197 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10198 10199 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10200 @*/ 10201 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10202 { 10203 PetscFunctionBegin; 10204 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10205 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10206 PetscFunctionReturn(PETSC_SUCCESS); 10207 } 10208 10209 /*@ 10210 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10211 10212 Neighbor-wise Collective 10213 10214 Input Parameters: 10215 + A - the left matrix 10216 . B - the right matrix 10217 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10218 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10219 10220 Output Parameter: 10221 . C - the product matrix 10222 10223 Level: intermediate 10224 10225 Notes: 10226 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10227 10228 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10229 10230 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10231 10232 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10233 actually needed. 10234 10235 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10236 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10237 10238 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10239 10240 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10241 @*/ 10242 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10243 { 10244 PetscFunctionBegin; 10245 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10246 PetscFunctionReturn(PETSC_SUCCESS); 10247 } 10248 10249 /*@ 10250 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10251 10252 Neighbor-wise Collective 10253 10254 Input Parameters: 10255 + A - the left matrix 10256 . B - the middle matrix 10257 . C - the right matrix 10258 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10259 - 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 10260 if the result is a dense matrix this is irrelevant 10261 10262 Output Parameter: 10263 . D - the product matrix 10264 10265 Level: intermediate 10266 10267 Notes: 10268 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10269 10270 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10271 10272 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10273 10274 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10275 actually needed. 10276 10277 If you have many matrices with the same non-zero structure to multiply, you 10278 should use `MAT_REUSE_MATRIX` in all calls but the first 10279 10280 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10281 10282 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10283 @*/ 10284 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10285 { 10286 PetscFunctionBegin; 10287 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10288 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10289 10290 if (scall == MAT_INITIAL_MATRIX) { 10291 PetscCall(MatProductCreate(A, B, C, D)); 10292 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10293 PetscCall(MatProductSetAlgorithm(*D, "default")); 10294 PetscCall(MatProductSetFill(*D, fill)); 10295 10296 (*D)->product->api_user = PETSC_TRUE; 10297 PetscCall(MatProductSetFromOptions(*D)); 10298 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, 10299 ((PetscObject)C)->type_name); 10300 PetscCall(MatProductSymbolic(*D)); 10301 } else { /* user may change input matrices when REUSE */ 10302 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10303 } 10304 PetscCall(MatProductNumeric(*D)); 10305 PetscFunctionReturn(PETSC_SUCCESS); 10306 } 10307 10308 /*@ 10309 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10310 10311 Collective 10312 10313 Input Parameters: 10314 + mat - the matrix 10315 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10316 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10317 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10318 10319 Output Parameter: 10320 . matredundant - redundant matrix 10321 10322 Level: advanced 10323 10324 Notes: 10325 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10326 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10327 10328 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10329 calling it. 10330 10331 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10332 10333 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10334 @*/ 10335 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10336 { 10337 MPI_Comm comm; 10338 PetscMPIInt size; 10339 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10340 Mat_Redundant *redund = NULL; 10341 PetscSubcomm psubcomm = NULL; 10342 MPI_Comm subcomm_in = subcomm; 10343 Mat *matseq; 10344 IS isrow, iscol; 10345 PetscBool newsubcomm = PETSC_FALSE; 10346 10347 PetscFunctionBegin; 10348 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10349 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10350 PetscAssertPointer(*matredundant, 5); 10351 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10352 } 10353 10354 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10355 if (size == 1 || nsubcomm == 1) { 10356 if (reuse == MAT_INITIAL_MATRIX) { 10357 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10358 } else { 10359 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"); 10360 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10361 } 10362 PetscFunctionReturn(PETSC_SUCCESS); 10363 } 10364 10365 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10366 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10367 MatCheckPreallocated(mat, 1); 10368 10369 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10370 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10371 /* create psubcomm, then get subcomm */ 10372 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10373 PetscCallMPI(MPI_Comm_size(comm, &size)); 10374 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10375 10376 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10377 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10378 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10379 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10380 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10381 newsubcomm = PETSC_TRUE; 10382 PetscCall(PetscSubcommDestroy(&psubcomm)); 10383 } 10384 10385 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10386 if (reuse == MAT_INITIAL_MATRIX) { 10387 mloc_sub = PETSC_DECIDE; 10388 nloc_sub = PETSC_DECIDE; 10389 if (bs < 1) { 10390 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10391 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10392 } else { 10393 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10394 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10395 } 10396 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10397 rstart = rend - mloc_sub; 10398 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10399 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10400 PetscCall(ISSetIdentity(iscol)); 10401 } else { /* reuse == MAT_REUSE_MATRIX */ 10402 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"); 10403 /* retrieve subcomm */ 10404 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10405 redund = (*matredundant)->redundant; 10406 isrow = redund->isrow; 10407 iscol = redund->iscol; 10408 matseq = redund->matseq; 10409 } 10410 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10411 10412 /* get matredundant over subcomm */ 10413 if (reuse == MAT_INITIAL_MATRIX) { 10414 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10415 10416 /* create a supporting struct and attach it to C for reuse */ 10417 PetscCall(PetscNew(&redund)); 10418 (*matredundant)->redundant = redund; 10419 redund->isrow = isrow; 10420 redund->iscol = iscol; 10421 redund->matseq = matseq; 10422 if (newsubcomm) { 10423 redund->subcomm = subcomm; 10424 } else { 10425 redund->subcomm = MPI_COMM_NULL; 10426 } 10427 } else { 10428 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10429 } 10430 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10431 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10432 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10433 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10434 } 10435 #endif 10436 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10437 PetscFunctionReturn(PETSC_SUCCESS); 10438 } 10439 10440 /*@C 10441 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10442 a given `Mat`. Each submatrix can span multiple procs. 10443 10444 Collective 10445 10446 Input Parameters: 10447 + mat - the matrix 10448 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10449 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10450 10451 Output Parameter: 10452 . subMat - parallel sub-matrices each spanning a given `subcomm` 10453 10454 Level: advanced 10455 10456 Notes: 10457 The submatrix partition across processors is dictated by `subComm` a 10458 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10459 is not restricted to be grouped with consecutive original MPI processes. 10460 10461 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10462 map directly to the layout of the original matrix [wrt the local 10463 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10464 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10465 the `subMat`. However the offDiagMat looses some columns - and this is 10466 reconstructed with `MatSetValues()` 10467 10468 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10469 10470 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10471 @*/ 10472 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10473 { 10474 PetscMPIInt commsize, subCommSize; 10475 10476 PetscFunctionBegin; 10477 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10478 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10479 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10480 10481 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"); 10482 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10483 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10484 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10485 PetscFunctionReturn(PETSC_SUCCESS); 10486 } 10487 10488 /*@ 10489 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10490 10491 Not Collective 10492 10493 Input Parameters: 10494 + mat - matrix to extract local submatrix from 10495 . isrow - local row indices for submatrix 10496 - iscol - local column indices for submatrix 10497 10498 Output Parameter: 10499 . submat - the submatrix 10500 10501 Level: intermediate 10502 10503 Notes: 10504 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10505 10506 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10507 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10508 10509 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10510 `MatSetValuesBlockedLocal()` will also be implemented. 10511 10512 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10513 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10514 10515 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10516 @*/ 10517 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10518 { 10519 PetscFunctionBegin; 10520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10521 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10522 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10523 PetscCheckSameComm(isrow, 2, iscol, 3); 10524 PetscAssertPointer(submat, 4); 10525 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10526 10527 if (mat->ops->getlocalsubmatrix) { 10528 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10529 } else { 10530 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10531 } 10532 PetscFunctionReturn(PETSC_SUCCESS); 10533 } 10534 10535 /*@ 10536 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10537 10538 Not Collective 10539 10540 Input Parameters: 10541 + mat - matrix to extract local submatrix from 10542 . isrow - local row indices for submatrix 10543 . iscol - local column indices for submatrix 10544 - submat - the submatrix 10545 10546 Level: intermediate 10547 10548 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10549 @*/ 10550 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10551 { 10552 PetscFunctionBegin; 10553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10554 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10555 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10556 PetscCheckSameComm(isrow, 2, iscol, 3); 10557 PetscAssertPointer(submat, 4); 10558 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10559 10560 if (mat->ops->restorelocalsubmatrix) { 10561 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10562 } else { 10563 PetscCall(MatDestroy(submat)); 10564 } 10565 *submat = NULL; 10566 PetscFunctionReturn(PETSC_SUCCESS); 10567 } 10568 10569 /*@ 10570 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10571 10572 Collective 10573 10574 Input Parameter: 10575 . mat - the matrix 10576 10577 Output Parameter: 10578 . is - if any rows have zero diagonals this contains the list of them 10579 10580 Level: developer 10581 10582 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10583 @*/ 10584 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10585 { 10586 PetscFunctionBegin; 10587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10588 PetscValidType(mat, 1); 10589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10590 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10591 10592 if (!mat->ops->findzerodiagonals) { 10593 Vec diag; 10594 const PetscScalar *a; 10595 PetscInt *rows; 10596 PetscInt rStart, rEnd, r, nrow = 0; 10597 10598 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10599 PetscCall(MatGetDiagonal(mat, diag)); 10600 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10601 PetscCall(VecGetArrayRead(diag, &a)); 10602 for (r = 0; r < rEnd - rStart; ++r) 10603 if (a[r] == 0.0) ++nrow; 10604 PetscCall(PetscMalloc1(nrow, &rows)); 10605 nrow = 0; 10606 for (r = 0; r < rEnd - rStart; ++r) 10607 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10608 PetscCall(VecRestoreArrayRead(diag, &a)); 10609 PetscCall(VecDestroy(&diag)); 10610 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10611 } else { 10612 PetscUseTypeMethod(mat, findzerodiagonals, is); 10613 } 10614 PetscFunctionReturn(PETSC_SUCCESS); 10615 } 10616 10617 /*@ 10618 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10619 10620 Collective 10621 10622 Input Parameter: 10623 . mat - the matrix 10624 10625 Output Parameter: 10626 . is - contains the list of rows with off block diagonal entries 10627 10628 Level: developer 10629 10630 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10631 @*/ 10632 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10633 { 10634 PetscFunctionBegin; 10635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10636 PetscValidType(mat, 1); 10637 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10638 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10639 10640 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10641 PetscFunctionReturn(PETSC_SUCCESS); 10642 } 10643 10644 /*@C 10645 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10646 10647 Collective; No Fortran Support 10648 10649 Input Parameter: 10650 . mat - the matrix 10651 10652 Output Parameter: 10653 . values - the block inverses in column major order (FORTRAN-like) 10654 10655 Level: advanced 10656 10657 Notes: 10658 The size of the blocks is determined by the block size of the matrix. 10659 10660 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10661 10662 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10663 10664 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10665 @*/ 10666 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10667 { 10668 PetscFunctionBegin; 10669 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10670 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10671 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10672 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10673 PetscFunctionReturn(PETSC_SUCCESS); 10674 } 10675 10676 /*@ 10677 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10678 10679 Collective; No Fortran Support 10680 10681 Input Parameters: 10682 + mat - the matrix 10683 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10684 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10685 10686 Output Parameter: 10687 . values - the block inverses in column major order (FORTRAN-like) 10688 10689 Level: advanced 10690 10691 Notes: 10692 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10693 10694 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10695 10696 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10697 @*/ 10698 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10699 { 10700 PetscFunctionBegin; 10701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10702 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10703 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10704 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10705 PetscFunctionReturn(PETSC_SUCCESS); 10706 } 10707 10708 /*@ 10709 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10710 10711 Collective 10712 10713 Input Parameters: 10714 + A - the matrix 10715 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10716 10717 Level: advanced 10718 10719 Note: 10720 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10721 10722 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10723 @*/ 10724 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10725 { 10726 const PetscScalar *vals; 10727 PetscInt *dnnz; 10728 PetscInt m, rstart, rend, bs, i, j; 10729 10730 PetscFunctionBegin; 10731 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10732 PetscCall(MatGetBlockSize(A, &bs)); 10733 PetscCall(MatGetLocalSize(A, &m, NULL)); 10734 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10735 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10736 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10737 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10738 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10739 PetscCall(PetscFree(dnnz)); 10740 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10741 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10742 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10743 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10744 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10745 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10746 PetscFunctionReturn(PETSC_SUCCESS); 10747 } 10748 10749 /*@ 10750 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10751 via `MatTransposeColoringCreate()`. 10752 10753 Collective 10754 10755 Input Parameter: 10756 . c - coloring context 10757 10758 Level: intermediate 10759 10760 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10761 @*/ 10762 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10763 { 10764 MatTransposeColoring matcolor = *c; 10765 10766 PetscFunctionBegin; 10767 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10768 if (--((PetscObject)matcolor)->refct > 0) { 10769 matcolor = NULL; 10770 PetscFunctionReturn(PETSC_SUCCESS); 10771 } 10772 10773 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10774 PetscCall(PetscFree(matcolor->rows)); 10775 PetscCall(PetscFree(matcolor->den2sp)); 10776 PetscCall(PetscFree(matcolor->colorforcol)); 10777 PetscCall(PetscFree(matcolor->columns)); 10778 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10779 PetscCall(PetscHeaderDestroy(c)); 10780 PetscFunctionReturn(PETSC_SUCCESS); 10781 } 10782 10783 /*@ 10784 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10785 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10786 `MatTransposeColoring` to sparse `B`. 10787 10788 Collective 10789 10790 Input Parameters: 10791 + coloring - coloring context created with `MatTransposeColoringCreate()` 10792 - B - sparse matrix 10793 10794 Output Parameter: 10795 . Btdense - dense matrix $B^T$ 10796 10797 Level: developer 10798 10799 Note: 10800 These are used internally for some implementations of `MatRARt()` 10801 10802 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10803 @*/ 10804 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10805 { 10806 PetscFunctionBegin; 10807 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10808 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10809 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10810 10811 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10812 PetscFunctionReturn(PETSC_SUCCESS); 10813 } 10814 10815 /*@ 10816 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10817 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10818 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10819 $C_{sp}$ from $C_{den}$. 10820 10821 Collective 10822 10823 Input Parameters: 10824 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10825 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10826 10827 Output Parameter: 10828 . Csp - sparse matrix 10829 10830 Level: developer 10831 10832 Note: 10833 These are used internally for some implementations of `MatRARt()` 10834 10835 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10836 @*/ 10837 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10838 { 10839 PetscFunctionBegin; 10840 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10841 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10842 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10843 10844 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10845 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10846 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10847 PetscFunctionReturn(PETSC_SUCCESS); 10848 } 10849 10850 /*@ 10851 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10852 10853 Collective 10854 10855 Input Parameters: 10856 + mat - the matrix product C 10857 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10858 10859 Output Parameter: 10860 . color - the new coloring context 10861 10862 Level: intermediate 10863 10864 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10865 `MatTransColoringApplyDenToSp()` 10866 @*/ 10867 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10868 { 10869 MatTransposeColoring c; 10870 MPI_Comm comm; 10871 10872 PetscFunctionBegin; 10873 PetscAssertPointer(color, 3); 10874 10875 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10876 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10877 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10878 c->ctype = iscoloring->ctype; 10879 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10880 *color = c; 10881 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10882 PetscFunctionReturn(PETSC_SUCCESS); 10883 } 10884 10885 /*@ 10886 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10887 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10888 10889 Not Collective 10890 10891 Input Parameter: 10892 . mat - the matrix 10893 10894 Output Parameter: 10895 . state - the current state 10896 10897 Level: intermediate 10898 10899 Notes: 10900 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10901 different matrices 10902 10903 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10904 10905 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10906 10907 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10908 @*/ 10909 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10910 { 10911 PetscFunctionBegin; 10912 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10913 *state = mat->nonzerostate; 10914 PetscFunctionReturn(PETSC_SUCCESS); 10915 } 10916 10917 /*@ 10918 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10919 matrices from each processor 10920 10921 Collective 10922 10923 Input Parameters: 10924 + comm - the communicators the parallel matrix will live on 10925 . seqmat - the input sequential matrices 10926 . n - number of local columns (or `PETSC_DECIDE`) 10927 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10928 10929 Output Parameter: 10930 . mpimat - the parallel matrix generated 10931 10932 Level: developer 10933 10934 Note: 10935 The number of columns of the matrix in EACH processor MUST be the same. 10936 10937 .seealso: [](ch_matrices), `Mat` 10938 @*/ 10939 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10940 { 10941 PetscMPIInt size; 10942 10943 PetscFunctionBegin; 10944 PetscCallMPI(MPI_Comm_size(comm, &size)); 10945 if (size == 1) { 10946 if (reuse == MAT_INITIAL_MATRIX) { 10947 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10948 } else { 10949 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10950 } 10951 PetscFunctionReturn(PETSC_SUCCESS); 10952 } 10953 10954 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"); 10955 10956 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10957 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10958 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10959 PetscFunctionReturn(PETSC_SUCCESS); 10960 } 10961 10962 /*@ 10963 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10964 10965 Collective 10966 10967 Input Parameters: 10968 + A - the matrix to create subdomains from 10969 - N - requested number of subdomains 10970 10971 Output Parameters: 10972 + n - number of subdomains resulting on this MPI process 10973 - iss - `IS` list with indices of subdomains on this MPI process 10974 10975 Level: advanced 10976 10977 Note: 10978 The number of subdomains must be smaller than the communicator size 10979 10980 .seealso: [](ch_matrices), `Mat`, `IS` 10981 @*/ 10982 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10983 { 10984 MPI_Comm comm, subcomm; 10985 PetscMPIInt size, rank, color; 10986 PetscInt rstart, rend, k; 10987 10988 PetscFunctionBegin; 10989 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10990 PetscCallMPI(MPI_Comm_size(comm, &size)); 10991 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10992 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); 10993 *n = 1; 10994 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 10995 color = rank / k; 10996 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10997 PetscCall(PetscMalloc1(1, iss)); 10998 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10999 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11000 PetscCallMPI(MPI_Comm_free(&subcomm)); 11001 PetscFunctionReturn(PETSC_SUCCESS); 11002 } 11003 11004 /*@ 11005 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11006 11007 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11008 If they are not the same, uses `MatMatMatMult()`. 11009 11010 Once the coarse grid problem is constructed, correct for interpolation operators 11011 that are not of full rank, which can legitimately happen in the case of non-nested 11012 geometric multigrid. 11013 11014 Input Parameters: 11015 + restrct - restriction operator 11016 . dA - fine grid matrix 11017 . interpolate - interpolation operator 11018 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11019 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11020 11021 Output Parameter: 11022 . A - the Galerkin coarse matrix 11023 11024 Options Database Key: 11025 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11026 11027 Level: developer 11028 11029 Note: 11030 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11031 11032 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11033 @*/ 11034 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11035 { 11036 IS zerorows; 11037 Vec diag; 11038 11039 PetscFunctionBegin; 11040 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11041 /* Construct the coarse grid matrix */ 11042 if (interpolate == restrct) { 11043 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11044 } else { 11045 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11046 } 11047 11048 /* If the interpolation matrix is not of full rank, A will have zero rows. 11049 This can legitimately happen in the case of non-nested geometric multigrid. 11050 In that event, we set the rows of the matrix to the rows of the identity, 11051 ignoring the equations (as the RHS will also be zero). */ 11052 11053 PetscCall(MatFindZeroRows(*A, &zerorows)); 11054 11055 if (zerorows != NULL) { /* if there are any zero rows */ 11056 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11057 PetscCall(MatGetDiagonal(*A, diag)); 11058 PetscCall(VecISSet(diag, zerorows, 1.0)); 11059 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11060 PetscCall(VecDestroy(&diag)); 11061 PetscCall(ISDestroy(&zerorows)); 11062 } 11063 PetscFunctionReturn(PETSC_SUCCESS); 11064 } 11065 11066 /*@C 11067 MatSetOperation - Allows user to set a matrix operation for any matrix type 11068 11069 Logically Collective 11070 11071 Input Parameters: 11072 + mat - the matrix 11073 . op - the name of the operation 11074 - f - the function that provides the operation 11075 11076 Level: developer 11077 11078 Example Usage: 11079 .vb 11080 extern PetscErrorCode usermult(Mat, Vec, Vec); 11081 11082 PetscCall(MatCreateXXX(comm, ..., &A)); 11083 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11084 .ve 11085 11086 Notes: 11087 See the file `include/petscmat.h` for a complete list of matrix 11088 operations, which all have the form MATOP_<OPERATION>, where 11089 <OPERATION> is the name (in all capital letters) of the 11090 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11091 11092 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11093 sequence as the usual matrix interface routines, since they 11094 are intended to be accessed via the usual matrix interface 11095 routines, e.g., 11096 .vb 11097 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11098 .ve 11099 11100 In particular each function MUST return `PETSC_SUCCESS` on success and 11101 nonzero on failure. 11102 11103 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11104 11105 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11106 @*/ 11107 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11108 { 11109 PetscFunctionBegin; 11110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11111 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11112 (((void (**)(void))mat->ops)[op]) = f; 11113 PetscFunctionReturn(PETSC_SUCCESS); 11114 } 11115 11116 /*@C 11117 MatGetOperation - Gets a matrix operation for any matrix type. 11118 11119 Not Collective 11120 11121 Input Parameters: 11122 + mat - the matrix 11123 - op - the name of the operation 11124 11125 Output Parameter: 11126 . f - the function that provides the operation 11127 11128 Level: developer 11129 11130 Example Usage: 11131 .vb 11132 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11133 11134 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11135 .ve 11136 11137 Notes: 11138 See the file include/petscmat.h for a complete list of matrix 11139 operations, which all have the form MATOP_<OPERATION>, where 11140 <OPERATION> is the name (in all capital letters) of the 11141 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11142 11143 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11144 11145 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11146 @*/ 11147 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11148 { 11149 PetscFunctionBegin; 11150 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11151 *f = (((void (**)(void))mat->ops)[op]); 11152 PetscFunctionReturn(PETSC_SUCCESS); 11153 } 11154 11155 /*@ 11156 MatHasOperation - Determines whether the given matrix supports the particular operation. 11157 11158 Not Collective 11159 11160 Input Parameters: 11161 + mat - the matrix 11162 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11163 11164 Output Parameter: 11165 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11166 11167 Level: advanced 11168 11169 Note: 11170 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11171 11172 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11173 @*/ 11174 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11175 { 11176 PetscFunctionBegin; 11177 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11178 PetscAssertPointer(has, 3); 11179 if (mat->ops->hasoperation) { 11180 PetscUseTypeMethod(mat, hasoperation, op, has); 11181 } else { 11182 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11183 else { 11184 *has = PETSC_FALSE; 11185 if (op == MATOP_CREATE_SUBMATRIX) { 11186 PetscMPIInt size; 11187 11188 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11189 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11190 } 11191 } 11192 } 11193 PetscFunctionReturn(PETSC_SUCCESS); 11194 } 11195 11196 /*@ 11197 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11198 11199 Collective 11200 11201 Input Parameter: 11202 . mat - the matrix 11203 11204 Output Parameter: 11205 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11206 11207 Level: beginner 11208 11209 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11210 @*/ 11211 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11212 { 11213 PetscFunctionBegin; 11214 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11215 PetscValidType(mat, 1); 11216 PetscAssertPointer(cong, 2); 11217 if (!mat->rmap || !mat->cmap) { 11218 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11219 PetscFunctionReturn(PETSC_SUCCESS); 11220 } 11221 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11222 PetscCall(PetscLayoutSetUp(mat->rmap)); 11223 PetscCall(PetscLayoutSetUp(mat->cmap)); 11224 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11225 if (*cong) mat->congruentlayouts = 1; 11226 else mat->congruentlayouts = 0; 11227 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11228 PetscFunctionReturn(PETSC_SUCCESS); 11229 } 11230 11231 PetscErrorCode MatSetInf(Mat A) 11232 { 11233 PetscFunctionBegin; 11234 PetscUseTypeMethod(A, setinf); 11235 PetscFunctionReturn(PETSC_SUCCESS); 11236 } 11237 11238 /*@ 11239 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 11240 and possibly removes small values from the graph structure. 11241 11242 Collective 11243 11244 Input Parameters: 11245 + A - the matrix 11246 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11247 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11248 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11249 . num_idx - size of 'index' array 11250 - index - array of block indices to use for graph strength of connection weight 11251 11252 Output Parameter: 11253 . graph - the resulting graph 11254 11255 Level: advanced 11256 11257 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11258 @*/ 11259 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11260 { 11261 PetscFunctionBegin; 11262 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11263 PetscValidType(A, 1); 11264 PetscValidLogicalCollectiveBool(A, scale, 3); 11265 PetscAssertPointer(graph, 7); 11266 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11267 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11268 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11269 PetscFunctionReturn(PETSC_SUCCESS); 11270 } 11271 11272 /*@ 11273 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11274 meaning the same memory is used for the matrix, and no new memory is allocated. 11275 11276 Collective 11277 11278 Input Parameters: 11279 + A - the matrix 11280 - 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 11281 11282 Level: intermediate 11283 11284 Developer Note: 11285 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11286 of the arrays in the data structure are unneeded. 11287 11288 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11289 @*/ 11290 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11291 { 11292 PetscFunctionBegin; 11293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11294 PetscUseTypeMethod(A, eliminatezeros, keep); 11295 PetscFunctionReturn(PETSC_SUCCESS); 11296 } 11297