1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscFunctionReturn(PETSC_SUCCESS); 759 } 760 761 /*@ 762 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 763 for matrices created with `MatGetFactor()` 764 765 Logically Collective 766 767 Input Parameters: 768 + A - the matrix 769 - prefix - the prefix to prepend to all option names for the factored matrix 770 771 Level: developer 772 773 Notes: 774 A hyphen (-) must NOT be given at the beginning of the prefix name. 775 The first character of all runtime options is AUTOMATICALLY the hyphen. 776 777 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 778 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 779 780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 781 @*/ 782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 783 { 784 PetscFunctionBegin; 785 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 786 if (prefix) { 787 PetscAssertPointer(prefix, 2); 788 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 789 if (prefix != A->factorprefix) { 790 PetscCall(PetscFree(A->factorprefix)); 791 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 792 } 793 } else PetscCall(PetscFree(A->factorprefix)); 794 PetscFunctionReturn(PETSC_SUCCESS); 795 } 796 797 /*@ 798 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 799 for matrices created with `MatGetFactor()` 800 801 Logically Collective 802 803 Input Parameters: 804 + A - the matrix 805 - prefix - the prefix to prepend to all option names for the factored matrix 806 807 Level: developer 808 809 Notes: 810 A hyphen (-) must NOT be given at the beginning of the prefix name. 811 The first character of all runtime options is AUTOMATICALLY the hyphen. 812 813 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 814 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 815 816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 817 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 818 `MatSetOptionsPrefix()` 819 @*/ 820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 821 { 822 size_t len1, len2, new_len; 823 824 PetscFunctionBegin; 825 PetscValidHeader(A, 1); 826 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 827 if (!A->factorprefix) { 828 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 829 PetscFunctionReturn(PETSC_SUCCESS); 830 } 831 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 832 833 PetscCall(PetscStrlen(A->factorprefix, &len1)); 834 PetscCall(PetscStrlen(prefix, &len2)); 835 new_len = len1 + len2 + 1; 836 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 837 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@ 842 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 843 matrix options in the database. 844 845 Logically Collective 846 847 Input Parameters: 848 + A - the matrix 849 - prefix - the prefix to prepend to all option names 850 851 Level: advanced 852 853 Note: 854 A hyphen (-) must NOT be given at the beginning of the prefix name. 855 The first character of all runtime options is AUTOMATICALLY the hyphen. 856 857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 858 @*/ 859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 860 { 861 PetscFunctionBegin; 862 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 863 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 864 PetscFunctionReturn(PETSC_SUCCESS); 865 } 866 867 /*@ 868 MatGetOptionsPrefix - Gets the prefix used for searching for all 869 matrix options in the database. 870 871 Not Collective 872 873 Input Parameter: 874 . A - the matrix 875 876 Output Parameter: 877 . prefix - pointer to the prefix string used 878 879 Level: advanced 880 881 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 882 @*/ 883 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 884 { 885 PetscFunctionBegin; 886 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 887 PetscAssertPointer(prefix, 2); 888 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 889 PetscFunctionReturn(PETSC_SUCCESS); 890 } 891 892 /*@ 893 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 894 895 Not Collective 896 897 Input Parameter: 898 . A - the matrix 899 900 Output Parameter: 901 . state - the object state 902 903 Level: advanced 904 905 Note: 906 Object state is an integer which gets increased every time 907 the object is changed. By saving and later querying the object state 908 one can determine whether information about the object is still current. 909 910 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 911 912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 913 @*/ 914 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 915 { 916 PetscFunctionBegin; 917 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 918 PetscAssertPointer(state, 2); 919 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 920 PetscFunctionReturn(PETSC_SUCCESS); 921 } 922 923 /*@ 924 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 925 926 Collective 927 928 Input Parameter: 929 . A - the matrix 930 931 Level: beginner 932 933 Notes: 934 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 935 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 936 makes all of the preallocation space available 937 938 Current values in the matrix are lost in this call 939 940 Currently only supported for `MATAIJ` matrices. 941 942 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 943 @*/ 944 PetscErrorCode MatResetPreallocation(Mat A) 945 { 946 PetscFunctionBegin; 947 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 948 PetscValidType(A, 1); 949 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 950 PetscFunctionReturn(PETSC_SUCCESS); 951 } 952 953 /*@ 954 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 955 956 Collective 957 958 Input Parameter: 959 . A - the matrix 960 961 Level: intermediate 962 963 Notes: 964 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 965 966 Currently only supported for `MATAIJ` matrices. 967 968 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 969 @*/ 970 PetscErrorCode MatResetHash(Mat A) 971 { 972 PetscFunctionBegin; 973 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 974 PetscValidType(A, 1); 975 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()"); 976 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 977 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 978 /* These flags are used to determine whether certain setups occur */ 979 A->was_assembled = PETSC_FALSE; 980 A->assembled = PETSC_FALSE; 981 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 982 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 983 PetscFunctionReturn(PETSC_SUCCESS); 984 } 985 986 /*@ 987 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 988 989 Collective 990 991 Input Parameter: 992 . A - the matrix 993 994 Level: advanced 995 996 Notes: 997 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 998 setting values in the matrix. 999 1000 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1001 1002 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1003 @*/ 1004 PetscErrorCode MatSetUp(Mat A) 1005 { 1006 PetscFunctionBegin; 1007 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1008 if (!((PetscObject)A)->type_name) { 1009 PetscMPIInt size; 1010 1011 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1012 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1013 } 1014 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1015 PetscCall(PetscLayoutSetUp(A->rmap)); 1016 PetscCall(PetscLayoutSetUp(A->cmap)); 1017 A->preallocated = PETSC_TRUE; 1018 PetscFunctionReturn(PETSC_SUCCESS); 1019 } 1020 1021 #if defined(PETSC_HAVE_SAWS) 1022 #include <petscviewersaws.h> 1023 #endif 1024 1025 /* 1026 If threadsafety is on extraneous matrices may be printed 1027 1028 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1029 */ 1030 #if !defined(PETSC_HAVE_THREADSAFETY) 1031 static PetscInt insidematview = 0; 1032 #endif 1033 1034 /*@ 1035 MatViewFromOptions - View properties of the matrix based on options set in the options database 1036 1037 Collective 1038 1039 Input Parameters: 1040 + A - the matrix 1041 . obj - optional additional object that provides the options prefix to use 1042 - name - command line option 1043 1044 Options Database Key: 1045 . -mat_view [viewertype]:... - the viewer and its options 1046 1047 Level: intermediate 1048 1049 Note: 1050 .vb 1051 If no value is provided ascii:stdout is used 1052 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1053 for example ascii::ascii_info prints just the information about the object not all details 1054 unless :append is given filename opens in write mode, overwriting what was already there 1055 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1056 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1057 socket[:port] defaults to the standard output port 1058 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1059 .ve 1060 1061 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1062 @*/ 1063 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1064 { 1065 PetscFunctionBegin; 1066 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1067 #if !defined(PETSC_HAVE_THREADSAFETY) 1068 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1069 #endif 1070 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1071 PetscFunctionReturn(PETSC_SUCCESS); 1072 } 1073 1074 /*@ 1075 MatView - display information about a matrix in a variety ways 1076 1077 Collective on viewer 1078 1079 Input Parameters: 1080 + mat - the matrix 1081 - viewer - visualization context 1082 1083 Options Database Keys: 1084 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1085 . -mat_view ::ascii_info_detail - Prints more detailed info 1086 . -mat_view - Prints matrix in ASCII format 1087 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1088 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1089 . -display <name> - Sets display name (default is host) 1090 . -draw_pause <sec> - Sets number of seconds to pause after display 1091 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1092 . -viewer_socket_machine <machine> - - 1093 . -viewer_socket_port <port> - - 1094 . -mat_view binary - save matrix to file in binary format 1095 - -viewer_binary_filename <name> - - 1096 1097 Level: beginner 1098 1099 Notes: 1100 The available visualization contexts include 1101 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1102 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1103 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1104 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1105 1106 The user can open alternative visualization contexts with 1107 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1108 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1109 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1110 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1111 1112 The user can call `PetscViewerPushFormat()` to specify the output 1113 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1114 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1115 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1116 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1117 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1118 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1119 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1120 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1121 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1122 1123 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1124 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1125 1126 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1127 1128 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1129 viewer is used. 1130 1131 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1132 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1133 1134 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1135 and then use the following mouse functions. 1136 .vb 1137 left mouse: zoom in 1138 middle mouse: zoom out 1139 right mouse: continue with the simulation 1140 .ve 1141 1142 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1143 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1144 @*/ 1145 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1146 { 1147 PetscInt rows, cols, rbs, cbs; 1148 PetscBool isascii, isstring, issaws; 1149 PetscViewerFormat format; 1150 PetscMPIInt size; 1151 1152 PetscFunctionBegin; 1153 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1154 PetscValidType(mat, 1); 1155 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1156 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1157 1158 PetscCall(PetscViewerGetFormat(viewer, &format)); 1159 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1160 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1161 1162 #if !defined(PETSC_HAVE_THREADSAFETY) 1163 insidematview++; 1164 #endif 1165 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1166 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1167 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1168 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"); 1169 1170 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1171 if (isascii) { 1172 if (!mat->preallocated) { 1173 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1174 #if !defined(PETSC_HAVE_THREADSAFETY) 1175 insidematview--; 1176 #endif 1177 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1178 PetscFunctionReturn(PETSC_SUCCESS); 1179 } 1180 if (!mat->assembled) { 1181 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1182 #if !defined(PETSC_HAVE_THREADSAFETY) 1183 insidematview--; 1184 #endif 1185 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1186 PetscFunctionReturn(PETSC_SUCCESS); 1187 } 1188 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1189 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1190 MatNullSpace nullsp, transnullsp; 1191 1192 PetscCall(PetscViewerASCIIPushTab(viewer)); 1193 PetscCall(MatGetSize(mat, &rows, &cols)); 1194 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1195 if (rbs != 1 || cbs != 1) { 1196 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" : "")); 1197 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1198 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1199 if (mat->factortype) { 1200 MatSolverType solver; 1201 PetscCall(MatFactorGetSolverType(mat, &solver)); 1202 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1203 } 1204 if (mat->ops->getinfo) { 1205 PetscBool is_constant_or_diagonal; 1206 1207 // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output 1208 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, "")); 1209 if (!is_constant_or_diagonal) { 1210 MatInfo info; 1211 1212 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1213 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1214 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1215 } 1216 } 1217 PetscCall(MatGetNullSpace(mat, &nullsp)); 1218 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1219 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1220 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1221 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1222 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1223 PetscCall(PetscViewerASCIIPushTab(viewer)); 1224 PetscCall(MatProductView(mat, viewer)); 1225 PetscCall(PetscViewerASCIIPopTab(viewer)); 1226 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1227 IS tmp; 1228 1229 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1230 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1231 PetscCall(PetscViewerASCIIPushTab(viewer)); 1232 PetscCall(ISView(tmp, viewer)); 1233 PetscCall(PetscViewerASCIIPopTab(viewer)); 1234 PetscCall(ISDestroy(&tmp)); 1235 } 1236 } 1237 } else if (issaws) { 1238 #if defined(PETSC_HAVE_SAWS) 1239 PetscMPIInt rank; 1240 1241 PetscCall(PetscObjectName((PetscObject)mat)); 1242 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1243 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1244 #endif 1245 } else if (isstring) { 1246 const char *type; 1247 PetscCall(MatGetType(mat, &type)); 1248 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1249 PetscTryTypeMethod(mat, view, viewer); 1250 } 1251 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1252 PetscCall(PetscViewerASCIIPushTab(viewer)); 1253 PetscUseTypeMethod(mat, viewnative, viewer); 1254 PetscCall(PetscViewerASCIIPopTab(viewer)); 1255 } else if (mat->ops->view) { 1256 PetscCall(PetscViewerASCIIPushTab(viewer)); 1257 PetscUseTypeMethod(mat, view, viewer); 1258 PetscCall(PetscViewerASCIIPopTab(viewer)); 1259 } 1260 if (isascii) { 1261 PetscCall(PetscViewerGetFormat(viewer, &format)); 1262 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1263 } 1264 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1265 #if !defined(PETSC_HAVE_THREADSAFETY) 1266 insidematview--; 1267 #endif 1268 PetscFunctionReturn(PETSC_SUCCESS); 1269 } 1270 1271 #if defined(PETSC_USE_DEBUG) 1272 #include <../src/sys/totalview/tv_data_display.h> 1273 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1274 { 1275 TV_add_row("Local rows", "int", &mat->rmap->n); 1276 TV_add_row("Local columns", "int", &mat->cmap->n); 1277 TV_add_row("Global rows", "int", &mat->rmap->N); 1278 TV_add_row("Global columns", "int", &mat->cmap->N); 1279 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1280 return TV_format_OK; 1281 } 1282 #endif 1283 1284 /*@ 1285 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1286 with `MatView()`. The matrix format is determined from the options database. 1287 Generates a parallel MPI matrix if the communicator has more than one 1288 processor. The default matrix type is `MATAIJ`. 1289 1290 Collective 1291 1292 Input Parameters: 1293 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1294 or some related function before a call to `MatLoad()` 1295 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1296 1297 Options Database Key: 1298 . -matload_block_size <bs> - set block size 1299 1300 Level: beginner 1301 1302 Notes: 1303 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1304 `Mat` before calling this routine if you wish to set it from the options database. 1305 1306 `MatLoad()` automatically loads into the options database any options 1307 given in the file filename.info where filename is the name of the file 1308 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1309 file will be ignored if you use the -viewer_binary_skip_info option. 1310 1311 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1312 sets the default matrix type AIJ and sets the local and global sizes. 1313 If type and/or size is already set, then the same are used. 1314 1315 In parallel, each processor can load a subset of rows (or the 1316 entire matrix). This routine is especially useful when a large 1317 matrix is stored on disk and only part of it is desired on each 1318 processor. For example, a parallel solver may access only some of 1319 the rows from each processor. The algorithm used here reads 1320 relatively small blocks of data rather than reading the entire 1321 matrix and then subsetting it. 1322 1323 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1324 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1325 or the sequence like 1326 .vb 1327 `PetscViewer` v; 1328 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1329 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1330 `PetscViewerSetFromOptions`(v); 1331 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1332 `PetscViewerFileSetName`(v,"datafile"); 1333 .ve 1334 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1335 $ -viewer_type {binary, hdf5} 1336 1337 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1338 and src/mat/tutorials/ex10.c with the second approach. 1339 1340 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1341 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1342 Multiple objects, both matrices and vectors, can be stored within the same file. 1343 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1344 1345 Most users should not need to know the details of the binary storage 1346 format, since `MatLoad()` and `MatView()` completely hide these details. 1347 But for anyone who is interested, the standard binary matrix storage 1348 format is 1349 1350 .vb 1351 PetscInt MAT_FILE_CLASSID 1352 PetscInt number of rows 1353 PetscInt number of columns 1354 PetscInt total number of nonzeros 1355 PetscInt *number nonzeros in each row 1356 PetscInt *column indices of all nonzeros (starting index is zero) 1357 PetscScalar *values of all nonzeros 1358 .ve 1359 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1360 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 1361 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1362 1363 PETSc automatically does the byte swapping for 1364 machines that store the bytes reversed. Thus if you write your own binary 1365 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1366 and `PetscBinaryWrite()` to see how this may be done. 1367 1368 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1369 Each processor's chunk is loaded independently by its owning MPI process. 1370 Multiple objects, both matrices and vectors, can be stored within the same file. 1371 They are looked up by their PetscObject name. 1372 1373 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1374 by default the same structure and naming of the AIJ arrays and column count 1375 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1376 $ save example.mat A b -v7.3 1377 can be directly read by this routine (see Reference 1 for details). 1378 1379 Depending on your MATLAB version, this format might be a default, 1380 otherwise you can set it as default in Preferences. 1381 1382 Unless -nocompression flag is used to save the file in MATLAB, 1383 PETSc must be configured with ZLIB package. 1384 1385 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1386 1387 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1388 1389 Corresponding `MatView()` is not yet implemented. 1390 1391 The loaded matrix is actually a transpose of the original one in MATLAB, 1392 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1393 With this format, matrix is automatically transposed by PETSc, 1394 unless the matrix is marked as SPD or symmetric 1395 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1396 1397 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1398 1399 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1400 @*/ 1401 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1402 { 1403 PetscBool flg; 1404 1405 PetscFunctionBegin; 1406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1407 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1408 1409 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1410 1411 flg = PETSC_FALSE; 1412 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1413 if (flg) { 1414 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1415 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1416 } 1417 flg = PETSC_FALSE; 1418 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1419 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1420 1421 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1422 PetscUseTypeMethod(mat, load, viewer); 1423 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1424 PetscFunctionReturn(PETSC_SUCCESS); 1425 } 1426 1427 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1428 { 1429 Mat_Redundant *redund = *redundant; 1430 1431 PetscFunctionBegin; 1432 if (redund) { 1433 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1434 PetscCall(ISDestroy(&redund->isrow)); 1435 PetscCall(ISDestroy(&redund->iscol)); 1436 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1437 } else { 1438 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1439 PetscCall(PetscFree(redund->sbuf_j)); 1440 PetscCall(PetscFree(redund->sbuf_a)); 1441 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1442 PetscCall(PetscFree(redund->rbuf_j[i])); 1443 PetscCall(PetscFree(redund->rbuf_a[i])); 1444 } 1445 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1446 } 1447 1448 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1449 PetscCall(PetscFree(redund)); 1450 } 1451 PetscFunctionReturn(PETSC_SUCCESS); 1452 } 1453 1454 /*@ 1455 MatDestroy - Frees space taken by a matrix. 1456 1457 Collective 1458 1459 Input Parameter: 1460 . A - the matrix 1461 1462 Level: beginner 1463 1464 Developer Note: 1465 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1466 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1467 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1468 if changes are needed here. 1469 1470 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1471 @*/ 1472 PetscErrorCode MatDestroy(Mat *A) 1473 { 1474 PetscFunctionBegin; 1475 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1476 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1477 if (--((PetscObject)*A)->refct > 0) { 1478 *A = NULL; 1479 PetscFunctionReturn(PETSC_SUCCESS); 1480 } 1481 1482 /* if memory was published with SAWs then destroy it */ 1483 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1484 PetscTryTypeMethod(*A, destroy); 1485 1486 PetscCall(PetscFree((*A)->factorprefix)); 1487 PetscCall(PetscFree((*A)->defaultvectype)); 1488 PetscCall(PetscFree((*A)->defaultrandtype)); 1489 PetscCall(PetscFree((*A)->bsizes)); 1490 PetscCall(PetscFree((*A)->solvertype)); 1491 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1492 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1493 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1494 PetscCall(MatProductClear(*A)); 1495 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1496 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1497 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1498 PetscCall(MatDestroy(&(*A)->schur)); 1499 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1500 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1501 PetscCall(PetscHeaderDestroy(A)); 1502 PetscFunctionReturn(PETSC_SUCCESS); 1503 } 1504 1505 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1506 /*@ 1507 MatSetValues - Inserts or adds a block of values into a matrix. 1508 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1509 MUST be called after all calls to `MatSetValues()` have been completed. 1510 1511 Not Collective 1512 1513 Input Parameters: 1514 + mat - the matrix 1515 . v - a logically two-dimensional array of values 1516 . m - the number of rows 1517 . idxm - the global indices of the rows 1518 . n - the number of columns 1519 . idxn - the global indices of the columns 1520 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1521 1522 Level: beginner 1523 1524 Notes: 1525 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1526 1527 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1528 options cannot be mixed without intervening calls to the assembly 1529 routines. 1530 1531 `MatSetValues()` uses 0-based row and column numbers in Fortran 1532 as well as in C. 1533 1534 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1535 simply ignored. This allows easily inserting element stiffness matrices 1536 with homogeneous Dirichlet boundary conditions that you don't want represented 1537 in the matrix. 1538 1539 Efficiency Alert: 1540 The routine `MatSetValuesBlocked()` may offer much better efficiency 1541 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1542 1543 Fortran Notes: 1544 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1545 .vb 1546 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1547 .ve 1548 1549 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1550 1551 Developer Note: 1552 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1553 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1554 1555 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1556 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1557 @*/ 1558 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1559 { 1560 PetscFunctionBeginHot; 1561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1562 PetscValidType(mat, 1); 1563 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1564 PetscAssertPointer(idxm, 3); 1565 PetscAssertPointer(idxn, 5); 1566 MatCheckPreallocated(mat, 1); 1567 1568 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1569 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1570 1571 if (PetscDefined(USE_DEBUG)) { 1572 PetscInt i, j; 1573 1574 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1575 if (v) { 1576 for (i = 0; i < m; i++) { 1577 for (j = 0; j < n; j++) { 1578 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1579 #if defined(PETSC_USE_COMPLEX) 1580 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]); 1581 #else 1582 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]); 1583 #endif 1584 } 1585 } 1586 } 1587 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); 1588 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); 1589 } 1590 1591 if (mat->assembled) { 1592 mat->was_assembled = PETSC_TRUE; 1593 mat->assembled = PETSC_FALSE; 1594 } 1595 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1596 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1597 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1598 PetscFunctionReturn(PETSC_SUCCESS); 1599 } 1600 1601 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1602 /*@ 1603 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1604 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1605 MUST be called after all calls to `MatSetValues()` have been completed. 1606 1607 Not Collective 1608 1609 Input Parameters: 1610 + mat - the matrix 1611 . v - a logically two-dimensional array of values 1612 . ism - the rows to provide 1613 . isn - the columns to provide 1614 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1615 1616 Level: beginner 1617 1618 Notes: 1619 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1620 1621 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1622 options cannot be mixed without intervening calls to the assembly 1623 routines. 1624 1625 `MatSetValues()` uses 0-based row and column numbers in Fortran 1626 as well as in C. 1627 1628 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1629 simply ignored. This allows easily inserting element stiffness matrices 1630 with homogeneous Dirichlet boundary conditions that you don't want represented 1631 in the matrix. 1632 1633 Efficiency Alert: 1634 The routine `MatSetValuesBlocked()` may offer much better efficiency 1635 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1636 1637 This is currently not optimized for any particular `ISType` 1638 1639 Developer Note: 1640 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1641 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1642 1643 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1644 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1645 @*/ 1646 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1647 { 1648 PetscInt m, n; 1649 const PetscInt *rows, *cols; 1650 1651 PetscFunctionBeginHot; 1652 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1653 PetscCall(ISGetIndices(ism, &rows)); 1654 PetscCall(ISGetIndices(isn, &cols)); 1655 PetscCall(ISGetLocalSize(ism, &m)); 1656 PetscCall(ISGetLocalSize(isn, &n)); 1657 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1658 PetscCall(ISRestoreIndices(ism, &rows)); 1659 PetscCall(ISRestoreIndices(isn, &cols)); 1660 PetscFunctionReturn(PETSC_SUCCESS); 1661 } 1662 1663 /*@ 1664 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1665 values into a matrix 1666 1667 Not Collective 1668 1669 Input Parameters: 1670 + mat - the matrix 1671 . row - the (block) row to set 1672 - v - a logically two-dimensional array of values 1673 1674 Level: intermediate 1675 1676 Notes: 1677 The values, `v`, are column-oriented (for the block version) and sorted 1678 1679 All the nonzero values in `row` must be provided 1680 1681 The matrix must have previously had its column indices set, likely by having been assembled. 1682 1683 `row` must belong to this MPI process 1684 1685 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1686 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1687 @*/ 1688 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1689 { 1690 PetscInt globalrow; 1691 1692 PetscFunctionBegin; 1693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1694 PetscValidType(mat, 1); 1695 PetscAssertPointer(v, 3); 1696 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1697 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1698 PetscFunctionReturn(PETSC_SUCCESS); 1699 } 1700 1701 /*@ 1702 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1703 values into a matrix 1704 1705 Not Collective 1706 1707 Input Parameters: 1708 + mat - the matrix 1709 . row - the (block) row to set 1710 - 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 1711 1712 Level: advanced 1713 1714 Notes: 1715 The values, `v`, are column-oriented for the block version. 1716 1717 All the nonzeros in `row` must be provided 1718 1719 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1720 1721 `row` must belong to this process 1722 1723 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1724 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1725 @*/ 1726 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1727 { 1728 PetscFunctionBeginHot; 1729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1730 PetscValidType(mat, 1); 1731 MatCheckPreallocated(mat, 1); 1732 PetscAssertPointer(v, 3); 1733 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1734 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1735 mat->insertmode = INSERT_VALUES; 1736 1737 if (mat->assembled) { 1738 mat->was_assembled = PETSC_TRUE; 1739 mat->assembled = PETSC_FALSE; 1740 } 1741 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1742 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1743 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1744 PetscFunctionReturn(PETSC_SUCCESS); 1745 } 1746 1747 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1748 /*@ 1749 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1750 Using structured grid indexing 1751 1752 Not Collective 1753 1754 Input Parameters: 1755 + mat - the matrix 1756 . m - number of rows being entered 1757 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1758 . n - number of columns being entered 1759 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1760 . v - a logically two-dimensional array of values 1761 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1762 1763 Level: beginner 1764 1765 Notes: 1766 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1767 1768 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1769 options cannot be mixed without intervening calls to the assembly 1770 routines. 1771 1772 The grid coordinates are across the entire grid, not just the local portion 1773 1774 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1775 as well as in C. 1776 1777 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1778 1779 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1780 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1781 1782 The columns and rows in the stencil passed in MUST be contained within the 1783 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1784 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1785 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1786 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1787 1788 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1789 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1790 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1791 `DM_BOUNDARY_PERIODIC` boundary type. 1792 1793 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 1794 a single value per point) you can skip filling those indices. 1795 1796 Inspired by the structured grid interface to the HYPRE package 1797 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1798 1799 Efficiency Alert: 1800 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1801 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1802 1803 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1804 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1805 @*/ 1806 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1807 { 1808 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1809 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1810 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1811 1812 PetscFunctionBegin; 1813 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1815 PetscValidType(mat, 1); 1816 PetscAssertPointer(idxm, 3); 1817 PetscAssertPointer(idxn, 5); 1818 1819 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1820 jdxm = buf; 1821 jdxn = buf + m; 1822 } else { 1823 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1824 jdxm = bufm; 1825 jdxn = bufn; 1826 } 1827 for (i = 0; i < m; i++) { 1828 for (j = 0; j < 3 - sdim; j++) dxm++; 1829 tmp = *dxm++ - starts[0]; 1830 for (j = 0; j < dim - 1; j++) { 1831 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1832 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1833 } 1834 if (mat->stencil.noc) dxm++; 1835 jdxm[i] = tmp; 1836 } 1837 for (i = 0; i < n; i++) { 1838 for (j = 0; j < 3 - sdim; j++) dxn++; 1839 tmp = *dxn++ - starts[0]; 1840 for (j = 0; j < dim - 1; j++) { 1841 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1842 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1843 } 1844 if (mat->stencil.noc) dxn++; 1845 jdxn[i] = tmp; 1846 } 1847 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1848 PetscCall(PetscFree2(bufm, bufn)); 1849 PetscFunctionReturn(PETSC_SUCCESS); 1850 } 1851 1852 /*@ 1853 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1854 Using structured grid indexing 1855 1856 Not Collective 1857 1858 Input Parameters: 1859 + mat - the matrix 1860 . m - number of rows being entered 1861 . idxm - grid coordinates for matrix rows being entered 1862 . n - number of columns being entered 1863 . idxn - grid coordinates for matrix columns being entered 1864 . v - a logically two-dimensional array of values 1865 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1866 1867 Level: beginner 1868 1869 Notes: 1870 By default the values, `v`, are row-oriented and unsorted. 1871 See `MatSetOption()` for other options. 1872 1873 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1874 options cannot be mixed without intervening calls to the assembly 1875 routines. 1876 1877 The grid coordinates are across the entire grid, not just the local portion 1878 1879 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1880 as well as in C. 1881 1882 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1883 1884 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1885 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1886 1887 The columns and rows in the stencil passed in MUST be contained within the 1888 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1889 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1890 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1891 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1892 1893 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1894 simply ignored. This allows easily inserting element stiffness matrices 1895 with homogeneous Dirichlet boundary conditions that you don't want represented 1896 in the matrix. 1897 1898 Inspired by the structured grid interface to the HYPRE package 1899 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1900 1901 Fortran Note: 1902 `idxm` and `idxn` should be declared as 1903 .vb 1904 MatStencil idxm(4,m),idxn(4,n) 1905 .ve 1906 and the values inserted using 1907 .vb 1908 idxm(MatStencil_i,1) = i 1909 idxm(MatStencil_j,1) = j 1910 idxm(MatStencil_k,1) = k 1911 etc 1912 .ve 1913 1914 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1915 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1916 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1917 @*/ 1918 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1919 { 1920 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1921 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1922 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1923 1924 PetscFunctionBegin; 1925 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1926 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1927 PetscValidType(mat, 1); 1928 PetscAssertPointer(idxm, 3); 1929 PetscAssertPointer(idxn, 5); 1930 PetscAssertPointer(v, 6); 1931 1932 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1933 jdxm = buf; 1934 jdxn = buf + m; 1935 } else { 1936 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1937 jdxm = bufm; 1938 jdxn = bufn; 1939 } 1940 for (i = 0; i < m; i++) { 1941 for (j = 0; j < 3 - sdim; j++) dxm++; 1942 tmp = *dxm++ - starts[0]; 1943 for (j = 0; j < sdim - 1; j++) { 1944 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1945 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1946 } 1947 dxm++; 1948 jdxm[i] = tmp; 1949 } 1950 for (i = 0; i < n; i++) { 1951 for (j = 0; j < 3 - sdim; j++) dxn++; 1952 tmp = *dxn++ - starts[0]; 1953 for (j = 0; j < sdim - 1; j++) { 1954 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1955 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1956 } 1957 dxn++; 1958 jdxn[i] = tmp; 1959 } 1960 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1961 PetscCall(PetscFree2(bufm, bufn)); 1962 PetscFunctionReturn(PETSC_SUCCESS); 1963 } 1964 1965 /*@ 1966 MatSetStencil - Sets the grid information for setting values into a matrix via 1967 `MatSetValuesStencil()` 1968 1969 Not Collective 1970 1971 Input Parameters: 1972 + mat - the matrix 1973 . dim - dimension of the grid 1, 2, or 3 1974 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1975 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1976 - dof - number of degrees of freedom per node 1977 1978 Level: beginner 1979 1980 Notes: 1981 Inspired by the structured grid interface to the HYPRE package 1982 (www.llnl.gov/CASC/hyper) 1983 1984 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1985 user. 1986 1987 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1988 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1989 @*/ 1990 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1991 { 1992 PetscFunctionBegin; 1993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1994 PetscAssertPointer(dims, 3); 1995 PetscAssertPointer(starts, 4); 1996 1997 mat->stencil.dim = dim + (dof > 1); 1998 for (PetscInt i = 0; i < dim; i++) { 1999 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2000 mat->stencil.starts[i] = starts[dim - i - 1]; 2001 } 2002 mat->stencil.dims[dim] = dof; 2003 mat->stencil.starts[dim] = 0; 2004 mat->stencil.noc = (PetscBool)(dof == 1); 2005 PetscFunctionReturn(PETSC_SUCCESS); 2006 } 2007 2008 /*@ 2009 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2010 2011 Not Collective 2012 2013 Input Parameters: 2014 + mat - the matrix 2015 . v - a logically two-dimensional array of values 2016 . m - the number of block rows 2017 . idxm - the global block indices 2018 . n - the number of block columns 2019 . idxn - the global block indices 2020 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2021 2022 Level: intermediate 2023 2024 Notes: 2025 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2026 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2027 2028 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2029 NOT the total number of rows/columns; for example, if the block size is 2 and 2030 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2031 The values in `idxm` would be 1 2; that is the first index for each block divided by 2032 the block size. 2033 2034 You must call `MatSetBlockSize()` when constructing this matrix (before 2035 preallocating it). 2036 2037 By default the values, `v`, are row-oriented, so the layout of 2038 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2039 2040 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2041 options cannot be mixed without intervening calls to the assembly 2042 routines. 2043 2044 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2045 as well as in C. 2046 2047 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2048 simply ignored. This allows easily inserting element stiffness matrices 2049 with homogeneous Dirichlet boundary conditions that you don't want represented 2050 in the matrix. 2051 2052 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2053 internal searching must be done to determine where to place the 2054 data in the matrix storage space. By instead inserting blocks of 2055 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2056 reduced. 2057 2058 Example: 2059 .vb 2060 Suppose m=n=2 and block size(bs) = 2 The array is 2061 2062 1 2 | 3 4 2063 5 6 | 7 8 2064 - - - | - - - 2065 9 10 | 11 12 2066 13 14 | 15 16 2067 2068 v[] should be passed in like 2069 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2070 2071 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2072 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2073 .ve 2074 2075 Fortran Notes: 2076 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2077 .vb 2078 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2079 .ve 2080 2081 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2082 2083 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2084 @*/ 2085 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2086 { 2087 PetscFunctionBeginHot; 2088 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2089 PetscValidType(mat, 1); 2090 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2091 PetscAssertPointer(idxm, 3); 2092 PetscAssertPointer(idxn, 5); 2093 MatCheckPreallocated(mat, 1); 2094 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2095 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2096 if (PetscDefined(USE_DEBUG)) { 2097 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2098 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2099 } 2100 if (PetscDefined(USE_DEBUG)) { 2101 PetscInt rbs, cbs, M, N, i; 2102 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2103 PetscCall(MatGetSize(mat, &M, &N)); 2104 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); 2105 for (i = 0; i < n; i++) 2106 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); 2107 } 2108 if (mat->assembled) { 2109 mat->was_assembled = PETSC_TRUE; 2110 mat->assembled = PETSC_FALSE; 2111 } 2112 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2113 if (mat->ops->setvaluesblocked) { 2114 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2115 } else { 2116 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2117 PetscInt i, j, bs, cbs; 2118 2119 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2120 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2121 iidxm = buf; 2122 iidxn = buf + m * bs; 2123 } else { 2124 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2125 iidxm = bufr; 2126 iidxn = bufc; 2127 } 2128 for (i = 0; i < m; i++) { 2129 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2130 } 2131 if (m != n || bs != cbs || idxm != idxn) { 2132 for (i = 0; i < n; i++) { 2133 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2134 } 2135 } else iidxn = iidxm; 2136 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2137 PetscCall(PetscFree2(bufr, bufc)); 2138 } 2139 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2140 PetscFunctionReturn(PETSC_SUCCESS); 2141 } 2142 2143 /*@ 2144 MatGetValues - Gets a block of local values from a matrix. 2145 2146 Not Collective; can only return values that are owned by the give process 2147 2148 Input Parameters: 2149 + mat - the matrix 2150 . v - a logically two-dimensional array for storing the values 2151 . m - the number of rows 2152 . idxm - the global indices of the rows 2153 . n - the number of columns 2154 - idxn - the global indices of the columns 2155 2156 Level: advanced 2157 2158 Notes: 2159 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2160 The values, `v`, are then returned in a row-oriented format, 2161 analogous to that used by default in `MatSetValues()`. 2162 2163 `MatGetValues()` uses 0-based row and column numbers in 2164 Fortran as well as in C. 2165 2166 `MatGetValues()` requires that the matrix has been assembled 2167 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2168 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2169 without intermediate matrix assembly. 2170 2171 Negative row or column indices will be ignored and those locations in `v` will be 2172 left unchanged. 2173 2174 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2175 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2176 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2177 2178 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2179 @*/ 2180 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2181 { 2182 PetscFunctionBegin; 2183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2184 PetscValidType(mat, 1); 2185 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2186 PetscAssertPointer(idxm, 3); 2187 PetscAssertPointer(idxn, 5); 2188 PetscAssertPointer(v, 6); 2189 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2190 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2191 MatCheckPreallocated(mat, 1); 2192 2193 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2194 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2195 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2196 PetscFunctionReturn(PETSC_SUCCESS); 2197 } 2198 2199 /*@ 2200 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2201 defined previously by `MatSetLocalToGlobalMapping()` 2202 2203 Not Collective 2204 2205 Input Parameters: 2206 + mat - the matrix 2207 . nrow - number of rows 2208 . irow - the row local indices 2209 . ncol - number of columns 2210 - icol - the column local indices 2211 2212 Output Parameter: 2213 . y - a logically two-dimensional array of values 2214 2215 Level: advanced 2216 2217 Notes: 2218 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2219 2220 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, 2221 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2222 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2223 with `MatSetLocalToGlobalMapping()`. 2224 2225 Developer Note: 2226 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2227 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2228 2229 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2230 `MatSetValuesLocal()`, `MatGetValues()` 2231 @*/ 2232 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2233 { 2234 PetscFunctionBeginHot; 2235 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2236 PetscValidType(mat, 1); 2237 MatCheckPreallocated(mat, 1); 2238 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2239 PetscAssertPointer(irow, 3); 2240 PetscAssertPointer(icol, 5); 2241 if (PetscDefined(USE_DEBUG)) { 2242 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2243 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2244 } 2245 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2246 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2247 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2248 else { 2249 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2250 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2251 irowm = buf; 2252 icolm = buf + nrow; 2253 } else { 2254 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2255 irowm = bufr; 2256 icolm = bufc; 2257 } 2258 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2259 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2260 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2261 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2262 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2263 PetscCall(PetscFree2(bufr, bufc)); 2264 } 2265 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2266 PetscFunctionReturn(PETSC_SUCCESS); 2267 } 2268 2269 /*@ 2270 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2271 the same size. Currently, this can only be called once and creates the given matrix. 2272 2273 Not Collective 2274 2275 Input Parameters: 2276 + mat - the matrix 2277 . nb - the number of blocks 2278 . bs - the number of rows (and columns) in each block 2279 . rows - a concatenation of the rows for each block 2280 - v - a concatenation of logically two-dimensional arrays of values 2281 2282 Level: advanced 2283 2284 Notes: 2285 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2286 2287 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2288 2289 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2290 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2291 @*/ 2292 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2293 { 2294 PetscFunctionBegin; 2295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2296 PetscValidType(mat, 1); 2297 PetscAssertPointer(rows, 4); 2298 PetscAssertPointer(v, 5); 2299 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2300 2301 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2302 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2303 else { 2304 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2305 } 2306 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2307 PetscFunctionReturn(PETSC_SUCCESS); 2308 } 2309 2310 /*@ 2311 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2312 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2313 using a local (per-processor) numbering. 2314 2315 Not Collective 2316 2317 Input Parameters: 2318 + x - the matrix 2319 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2320 - cmapping - column mapping 2321 2322 Level: intermediate 2323 2324 Note: 2325 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2326 2327 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2328 @*/ 2329 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2330 { 2331 PetscFunctionBegin; 2332 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2333 PetscValidType(x, 1); 2334 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2335 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2336 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2337 else { 2338 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2339 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2340 } 2341 PetscFunctionReturn(PETSC_SUCCESS); 2342 } 2343 2344 /*@ 2345 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2346 2347 Not Collective 2348 2349 Input Parameter: 2350 . A - the matrix 2351 2352 Output Parameters: 2353 + rmapping - row mapping 2354 - cmapping - column mapping 2355 2356 Level: advanced 2357 2358 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2359 @*/ 2360 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2361 { 2362 PetscFunctionBegin; 2363 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2364 PetscValidType(A, 1); 2365 if (rmapping) { 2366 PetscAssertPointer(rmapping, 2); 2367 *rmapping = A->rmap->mapping; 2368 } 2369 if (cmapping) { 2370 PetscAssertPointer(cmapping, 3); 2371 *cmapping = A->cmap->mapping; 2372 } 2373 PetscFunctionReturn(PETSC_SUCCESS); 2374 } 2375 2376 /*@ 2377 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2378 2379 Logically Collective 2380 2381 Input Parameters: 2382 + A - the matrix 2383 . rmap - row layout 2384 - cmap - column layout 2385 2386 Level: advanced 2387 2388 Note: 2389 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2390 2391 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2392 @*/ 2393 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2394 { 2395 PetscFunctionBegin; 2396 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2397 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2398 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2399 PetscFunctionReturn(PETSC_SUCCESS); 2400 } 2401 2402 /*@ 2403 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2404 2405 Not Collective 2406 2407 Input Parameter: 2408 . A - the matrix 2409 2410 Output Parameters: 2411 + rmap - row layout 2412 - cmap - column layout 2413 2414 Level: advanced 2415 2416 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2417 @*/ 2418 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2419 { 2420 PetscFunctionBegin; 2421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2422 PetscValidType(A, 1); 2423 if (rmap) { 2424 PetscAssertPointer(rmap, 2); 2425 *rmap = A->rmap; 2426 } 2427 if (cmap) { 2428 PetscAssertPointer(cmap, 3); 2429 *cmap = A->cmap; 2430 } 2431 PetscFunctionReturn(PETSC_SUCCESS); 2432 } 2433 2434 /*@ 2435 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2436 using a local numbering of the rows and columns. 2437 2438 Not Collective 2439 2440 Input Parameters: 2441 + mat - the matrix 2442 . nrow - number of rows 2443 . irow - the row local indices 2444 . ncol - number of columns 2445 . icol - the column local indices 2446 . y - a logically two-dimensional array of values 2447 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2448 2449 Level: intermediate 2450 2451 Notes: 2452 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2453 2454 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2455 options cannot be mixed without intervening calls to the assembly 2456 routines. 2457 2458 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2459 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2460 2461 Fortran Notes: 2462 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2463 .vb 2464 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2465 .ve 2466 2467 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2468 2469 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2470 `MatGetValuesLocal()` 2471 @*/ 2472 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2473 { 2474 PetscFunctionBeginHot; 2475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2476 PetscValidType(mat, 1); 2477 MatCheckPreallocated(mat, 1); 2478 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2479 PetscAssertPointer(irow, 3); 2480 PetscAssertPointer(icol, 5); 2481 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2482 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2483 if (PetscDefined(USE_DEBUG)) { 2484 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2485 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2486 } 2487 2488 if (mat->assembled) { 2489 mat->was_assembled = PETSC_TRUE; 2490 mat->assembled = PETSC_FALSE; 2491 } 2492 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2493 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2494 else { 2495 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2496 const PetscInt *irowm, *icolm; 2497 2498 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2499 bufr = buf; 2500 bufc = buf + nrow; 2501 irowm = bufr; 2502 icolm = bufc; 2503 } else { 2504 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2505 irowm = bufr; 2506 icolm = bufc; 2507 } 2508 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2509 else irowm = irow; 2510 if (mat->cmap->mapping) { 2511 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2512 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2513 } else icolm = irowm; 2514 } else icolm = icol; 2515 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2516 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2517 } 2518 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2519 PetscFunctionReturn(PETSC_SUCCESS); 2520 } 2521 2522 /*@ 2523 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2524 using a local ordering of the nodes a block at a time. 2525 2526 Not Collective 2527 2528 Input Parameters: 2529 + mat - the matrix 2530 . nrow - number of rows 2531 . irow - the row local indices 2532 . ncol - number of columns 2533 . icol - the column local indices 2534 . y - a logically two-dimensional array of values 2535 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2536 2537 Level: intermediate 2538 2539 Notes: 2540 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2541 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2542 2543 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2544 options cannot be mixed without intervening calls to the assembly 2545 routines. 2546 2547 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2548 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2549 2550 Fortran Notes: 2551 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2552 .vb 2553 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2554 .ve 2555 2556 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2557 2558 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2559 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2560 @*/ 2561 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2562 { 2563 PetscFunctionBeginHot; 2564 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2565 PetscValidType(mat, 1); 2566 MatCheckPreallocated(mat, 1); 2567 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2568 PetscAssertPointer(irow, 3); 2569 PetscAssertPointer(icol, 5); 2570 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2571 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2572 if (PetscDefined(USE_DEBUG)) { 2573 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2574 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); 2575 } 2576 2577 if (mat->assembled) { 2578 mat->was_assembled = PETSC_TRUE; 2579 mat->assembled = PETSC_FALSE; 2580 } 2581 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2582 PetscInt irbs, rbs; 2583 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2584 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2585 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2586 } 2587 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2588 PetscInt icbs, cbs; 2589 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2590 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2591 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2592 } 2593 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2594 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2595 else { 2596 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2597 const PetscInt *irowm, *icolm; 2598 2599 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2600 bufr = buf; 2601 bufc = buf + nrow; 2602 irowm = bufr; 2603 icolm = bufc; 2604 } else { 2605 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2606 irowm = bufr; 2607 icolm = bufc; 2608 } 2609 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2610 else irowm = irow; 2611 if (mat->cmap->mapping) { 2612 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2613 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2614 } else icolm = irowm; 2615 } else icolm = icol; 2616 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2617 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2618 } 2619 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2620 PetscFunctionReturn(PETSC_SUCCESS); 2621 } 2622 2623 /*@ 2624 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2625 2626 Collective 2627 2628 Input Parameters: 2629 + mat - the matrix 2630 - x - the vector to be multiplied 2631 2632 Output Parameter: 2633 . y - the result 2634 2635 Level: developer 2636 2637 Note: 2638 The vectors `x` and `y` cannot be the same. I.e., one cannot 2639 call `MatMultDiagonalBlock`(A,y,y). 2640 2641 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2642 @*/ 2643 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2644 { 2645 PetscFunctionBegin; 2646 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2647 PetscValidType(mat, 1); 2648 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2649 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2650 2651 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2652 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2653 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2654 MatCheckPreallocated(mat, 1); 2655 2656 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2657 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2658 PetscFunctionReturn(PETSC_SUCCESS); 2659 } 2660 2661 /*@ 2662 MatMult - Computes the matrix-vector product, $y = Ax$. 2663 2664 Neighbor-wise Collective 2665 2666 Input Parameters: 2667 + mat - the matrix 2668 - x - the vector to be multiplied 2669 2670 Output Parameter: 2671 . y - the result 2672 2673 Level: beginner 2674 2675 Note: 2676 The vectors `x` and `y` cannot be the same. I.e., one cannot 2677 call `MatMult`(A,y,y). 2678 2679 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2680 @*/ 2681 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2682 { 2683 PetscFunctionBegin; 2684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2685 PetscValidType(mat, 1); 2686 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2687 VecCheckAssembled(x); 2688 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2689 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2690 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2691 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2692 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); 2693 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); 2694 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); 2695 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); 2696 PetscCall(VecSetErrorIfLocked(y, 3)); 2697 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2698 MatCheckPreallocated(mat, 1); 2699 2700 PetscCall(VecLockReadPush(x)); 2701 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2702 PetscUseTypeMethod(mat, mult, x, y); 2703 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2704 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2705 PetscCall(VecLockReadPop(x)); 2706 PetscFunctionReturn(PETSC_SUCCESS); 2707 } 2708 2709 /*@ 2710 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2711 2712 Neighbor-wise Collective 2713 2714 Input Parameters: 2715 + mat - the matrix 2716 - x - the vector to be multiplied 2717 2718 Output Parameter: 2719 . y - the result 2720 2721 Level: beginner 2722 2723 Notes: 2724 The vectors `x` and `y` cannot be the same. I.e., one cannot 2725 call `MatMultTranspose`(A,y,y). 2726 2727 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2728 use `MatMultHermitianTranspose()` 2729 2730 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2731 @*/ 2732 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2733 { 2734 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2735 2736 PetscFunctionBegin; 2737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2738 PetscValidType(mat, 1); 2739 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2740 VecCheckAssembled(x); 2741 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2742 2743 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2744 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2745 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2746 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); 2747 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); 2748 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); 2749 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); 2750 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2751 MatCheckPreallocated(mat, 1); 2752 2753 if (!mat->ops->multtranspose) { 2754 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2755 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); 2756 } else op = mat->ops->multtranspose; 2757 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2758 PetscCall(VecLockReadPush(x)); 2759 PetscCall((*op)(mat, x, y)); 2760 PetscCall(VecLockReadPop(x)); 2761 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2762 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2763 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2764 PetscFunctionReturn(PETSC_SUCCESS); 2765 } 2766 2767 /*@ 2768 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2769 2770 Neighbor-wise Collective 2771 2772 Input Parameters: 2773 + mat - the matrix 2774 - x - the vector to be multiplied 2775 2776 Output Parameter: 2777 . y - the result 2778 2779 Level: beginner 2780 2781 Notes: 2782 The vectors `x` and `y` cannot be the same. I.e., one cannot 2783 call `MatMultHermitianTranspose`(A,y,y). 2784 2785 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2786 2787 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2788 2789 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2790 @*/ 2791 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2792 { 2793 PetscFunctionBegin; 2794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2795 PetscValidType(mat, 1); 2796 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2797 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2798 2799 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2800 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2801 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2802 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); 2803 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); 2804 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); 2805 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); 2806 MatCheckPreallocated(mat, 1); 2807 2808 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2809 #if defined(PETSC_USE_COMPLEX) 2810 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2811 PetscCall(VecLockReadPush(x)); 2812 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2813 else PetscUseTypeMethod(mat, mult, x, y); 2814 PetscCall(VecLockReadPop(x)); 2815 } else { 2816 Vec w; 2817 PetscCall(VecDuplicate(x, &w)); 2818 PetscCall(VecCopy(x, w)); 2819 PetscCall(VecConjugate(w)); 2820 PetscCall(MatMultTranspose(mat, w, y)); 2821 PetscCall(VecDestroy(&w)); 2822 PetscCall(VecConjugate(y)); 2823 } 2824 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2825 #else 2826 PetscCall(MatMultTranspose(mat, x, y)); 2827 #endif 2828 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2829 PetscFunctionReturn(PETSC_SUCCESS); 2830 } 2831 2832 /*@ 2833 MatMultAdd - Computes $v3 = v2 + A * v1$. 2834 2835 Neighbor-wise Collective 2836 2837 Input Parameters: 2838 + mat - the matrix 2839 . v1 - the vector to be multiplied by `mat` 2840 - v2 - the vector to be added to the result 2841 2842 Output Parameter: 2843 . v3 - the result 2844 2845 Level: beginner 2846 2847 Note: 2848 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2849 call `MatMultAdd`(A,v1,v2,v1). 2850 2851 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2852 @*/ 2853 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2854 { 2855 PetscFunctionBegin; 2856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2857 PetscValidType(mat, 1); 2858 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2859 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2860 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2861 2862 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2863 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2864 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); 2865 /* 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); 2866 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); */ 2867 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); 2868 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); 2869 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2870 MatCheckPreallocated(mat, 1); 2871 2872 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2873 PetscCall(VecLockReadPush(v1)); 2874 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2875 PetscCall(VecLockReadPop(v1)); 2876 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2877 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2878 PetscFunctionReturn(PETSC_SUCCESS); 2879 } 2880 2881 /*@ 2882 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2883 2884 Neighbor-wise Collective 2885 2886 Input Parameters: 2887 + mat - the matrix 2888 . v1 - the vector to be multiplied by the transpose of the matrix 2889 - v2 - the vector to be added to the result 2890 2891 Output Parameter: 2892 . v3 - the result 2893 2894 Level: beginner 2895 2896 Note: 2897 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2898 call `MatMultTransposeAdd`(A,v1,v2,v1). 2899 2900 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2901 @*/ 2902 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2903 { 2904 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2905 2906 PetscFunctionBegin; 2907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2908 PetscValidType(mat, 1); 2909 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2910 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2911 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2912 2913 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2914 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2915 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); 2916 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); 2917 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); 2918 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2919 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2920 MatCheckPreallocated(mat, 1); 2921 2922 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2923 PetscCall(VecLockReadPush(v1)); 2924 PetscCall((*op)(mat, v1, v2, v3)); 2925 PetscCall(VecLockReadPop(v1)); 2926 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2927 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2928 PetscFunctionReturn(PETSC_SUCCESS); 2929 } 2930 2931 /*@ 2932 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2933 2934 Neighbor-wise Collective 2935 2936 Input Parameters: 2937 + mat - the matrix 2938 . v1 - the vector to be multiplied by the Hermitian transpose 2939 - v2 - the vector to be added to the result 2940 2941 Output Parameter: 2942 . v3 - the result 2943 2944 Level: beginner 2945 2946 Note: 2947 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2948 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2949 2950 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2951 @*/ 2952 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2953 { 2954 PetscFunctionBegin; 2955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2956 PetscValidType(mat, 1); 2957 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2958 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2959 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2960 2961 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2962 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2963 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2964 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); 2965 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); 2966 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); 2967 MatCheckPreallocated(mat, 1); 2968 2969 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2970 PetscCall(VecLockReadPush(v1)); 2971 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2972 else { 2973 Vec w, z; 2974 PetscCall(VecDuplicate(v1, &w)); 2975 PetscCall(VecCopy(v1, w)); 2976 PetscCall(VecConjugate(w)); 2977 PetscCall(VecDuplicate(v3, &z)); 2978 PetscCall(MatMultTranspose(mat, w, z)); 2979 PetscCall(VecDestroy(&w)); 2980 PetscCall(VecConjugate(z)); 2981 if (v2 != v3) { 2982 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2983 } else { 2984 PetscCall(VecAXPY(v3, 1.0, z)); 2985 } 2986 PetscCall(VecDestroy(&z)); 2987 } 2988 PetscCall(VecLockReadPop(v1)); 2989 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2990 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2991 PetscFunctionReturn(PETSC_SUCCESS); 2992 } 2993 2994 /*@ 2995 MatGetFactorType - gets the type of factorization a matrix is 2996 2997 Not Collective 2998 2999 Input Parameter: 3000 . mat - the matrix 3001 3002 Output Parameter: 3003 . 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` 3004 3005 Level: intermediate 3006 3007 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3008 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3009 @*/ 3010 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3011 { 3012 PetscFunctionBegin; 3013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3014 PetscValidType(mat, 1); 3015 PetscAssertPointer(t, 2); 3016 *t = mat->factortype; 3017 PetscFunctionReturn(PETSC_SUCCESS); 3018 } 3019 3020 /*@ 3021 MatSetFactorType - sets the type of factorization a matrix is 3022 3023 Logically Collective 3024 3025 Input Parameters: 3026 + mat - the matrix 3027 - 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` 3028 3029 Level: intermediate 3030 3031 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3032 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3033 @*/ 3034 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3035 { 3036 PetscFunctionBegin; 3037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3038 PetscValidType(mat, 1); 3039 mat->factortype = t; 3040 PetscFunctionReturn(PETSC_SUCCESS); 3041 } 3042 3043 /*@ 3044 MatGetInfo - Returns information about matrix storage (number of 3045 nonzeros, memory, etc.). 3046 3047 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3048 3049 Input Parameters: 3050 + mat - the matrix 3051 - 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) 3052 3053 Output Parameter: 3054 . info - matrix information context 3055 3056 Options Database Key: 3057 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3058 3059 Level: intermediate 3060 3061 Notes: 3062 The `MatInfo` context contains a variety of matrix data, including 3063 number of nonzeros allocated and used, number of mallocs during 3064 matrix assembly, etc. Additional information for factored matrices 3065 is provided (such as the fill ratio, number of mallocs during 3066 factorization, etc.). 3067 3068 Example: 3069 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3070 data within the `MatInfo` context. For example, 3071 .vb 3072 MatInfo info; 3073 Mat A; 3074 double mal, nz_a, nz_u; 3075 3076 MatGetInfo(A, MAT_LOCAL, &info); 3077 mal = info.mallocs; 3078 nz_a = info.nz_allocated; 3079 .ve 3080 3081 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3082 @*/ 3083 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3084 { 3085 PetscFunctionBegin; 3086 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3087 PetscValidType(mat, 1); 3088 PetscAssertPointer(info, 3); 3089 MatCheckPreallocated(mat, 1); 3090 PetscUseTypeMethod(mat, getinfo, flag, info); 3091 PetscFunctionReturn(PETSC_SUCCESS); 3092 } 3093 3094 /* 3095 This is used by external packages where it is not easy to get the info from the actual 3096 matrix factorization. 3097 */ 3098 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3099 { 3100 PetscFunctionBegin; 3101 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3102 PetscFunctionReturn(PETSC_SUCCESS); 3103 } 3104 3105 /*@ 3106 MatLUFactor - Performs in-place LU factorization of matrix. 3107 3108 Collective 3109 3110 Input Parameters: 3111 + mat - the matrix 3112 . row - row permutation 3113 . col - column permutation 3114 - info - options for factorization, includes 3115 .vb 3116 fill - expected fill as ratio of original fill. 3117 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3118 Run with the option -info to determine an optimal value to use 3119 .ve 3120 3121 Level: developer 3122 3123 Notes: 3124 Most users should employ the `KSP` interface for linear solvers 3125 instead of working directly with matrix algebra routines such as this. 3126 See, e.g., `KSPCreate()`. 3127 3128 This changes the state of the matrix to a factored matrix; it cannot be used 3129 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3130 3131 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3132 when not using `KSP`. 3133 3134 Developer Note: 3135 The Fortran interface is not autogenerated as the 3136 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3137 3138 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3139 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3140 @*/ 3141 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3142 { 3143 MatFactorInfo tinfo; 3144 3145 PetscFunctionBegin; 3146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3147 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3148 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3149 if (info) PetscAssertPointer(info, 4); 3150 PetscValidType(mat, 1); 3151 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3152 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3153 MatCheckPreallocated(mat, 1); 3154 if (!info) { 3155 PetscCall(MatFactorInfoInitialize(&tinfo)); 3156 info = &tinfo; 3157 } 3158 3159 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3160 PetscUseTypeMethod(mat, lufactor, row, col, info); 3161 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3162 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3163 PetscFunctionReturn(PETSC_SUCCESS); 3164 } 3165 3166 /*@ 3167 MatILUFactor - Performs in-place ILU factorization of matrix. 3168 3169 Collective 3170 3171 Input Parameters: 3172 + mat - the matrix 3173 . row - row permutation 3174 . col - column permutation 3175 - info - structure containing 3176 .vb 3177 levels - number of levels of fill. 3178 expected fill - as ratio of original fill. 3179 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3180 missing diagonal entries) 3181 .ve 3182 3183 Level: developer 3184 3185 Notes: 3186 Most users should employ the `KSP` interface for linear solvers 3187 instead of working directly with matrix algebra routines such as this. 3188 See, e.g., `KSPCreate()`. 3189 3190 Probably really in-place only when level of fill is zero, otherwise allocates 3191 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3192 when not using `KSP`. 3193 3194 Developer Note: 3195 The Fortran interface is not autogenerated as the 3196 interface definition cannot be generated correctly [due to MatFactorInfo] 3197 3198 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3199 @*/ 3200 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3201 { 3202 PetscFunctionBegin; 3203 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3204 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3205 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3206 PetscAssertPointer(info, 4); 3207 PetscValidType(mat, 1); 3208 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3209 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3210 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3211 MatCheckPreallocated(mat, 1); 3212 3213 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3214 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3215 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3216 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3217 PetscFunctionReturn(PETSC_SUCCESS); 3218 } 3219 3220 /*@ 3221 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3222 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3223 3224 Collective 3225 3226 Input Parameters: 3227 + fact - the factor matrix obtained with `MatGetFactor()` 3228 . mat - the matrix 3229 . row - the row permutation 3230 . col - the column permutation 3231 - info - options for factorization, includes 3232 .vb 3233 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3234 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3235 .ve 3236 3237 Level: developer 3238 3239 Notes: 3240 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3241 3242 Most users should employ the simplified `KSP` interface for linear solvers 3243 instead of working directly with matrix algebra routines such as this. 3244 See, e.g., `KSPCreate()`. 3245 3246 Developer Note: 3247 The Fortran interface is not autogenerated as the 3248 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3249 3250 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3251 @*/ 3252 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3253 { 3254 MatFactorInfo tinfo; 3255 3256 PetscFunctionBegin; 3257 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3259 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3260 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3261 if (info) PetscAssertPointer(info, 5); 3262 PetscValidType(fact, 1); 3263 PetscValidType(mat, 2); 3264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3265 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3266 MatCheckPreallocated(mat, 2); 3267 if (!info) { 3268 PetscCall(MatFactorInfoInitialize(&tinfo)); 3269 info = &tinfo; 3270 } 3271 3272 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3273 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3274 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3275 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3276 PetscFunctionReturn(PETSC_SUCCESS); 3277 } 3278 3279 /*@ 3280 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3281 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3282 3283 Collective 3284 3285 Input Parameters: 3286 + fact - the factor matrix obtained with `MatGetFactor()` 3287 . mat - the matrix 3288 - info - options for factorization 3289 3290 Level: developer 3291 3292 Notes: 3293 See `MatLUFactor()` for in-place factorization. See 3294 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3295 3296 Most users should employ the `KSP` interface for linear solvers 3297 instead of working directly with matrix algebra routines such as this. 3298 See, e.g., `KSPCreate()`. 3299 3300 Developer Note: 3301 The Fortran interface is not autogenerated as the 3302 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3303 3304 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3305 @*/ 3306 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3307 { 3308 MatFactorInfo tinfo; 3309 3310 PetscFunctionBegin; 3311 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3312 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3313 PetscValidType(fact, 1); 3314 PetscValidType(mat, 2); 3315 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3316 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, 3317 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3318 3319 MatCheckPreallocated(mat, 2); 3320 if (!info) { 3321 PetscCall(MatFactorInfoInitialize(&tinfo)); 3322 info = &tinfo; 3323 } 3324 3325 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3326 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3327 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3328 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3329 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3330 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3331 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3332 PetscFunctionReturn(PETSC_SUCCESS); 3333 } 3334 3335 /*@ 3336 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3337 symmetric matrix. 3338 3339 Collective 3340 3341 Input Parameters: 3342 + mat - the matrix 3343 . perm - row and column permutations 3344 - info - expected fill as ratio of original fill 3345 3346 Level: developer 3347 3348 Notes: 3349 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3350 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3351 3352 Most users should employ the `KSP` interface for linear solvers 3353 instead of working directly with matrix algebra routines such as this. 3354 See, e.g., `KSPCreate()`. 3355 3356 Developer Note: 3357 The Fortran interface is not autogenerated as the 3358 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3359 3360 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3361 `MatGetOrdering()` 3362 @*/ 3363 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3364 { 3365 MatFactorInfo tinfo; 3366 3367 PetscFunctionBegin; 3368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3369 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3370 if (info) PetscAssertPointer(info, 3); 3371 PetscValidType(mat, 1); 3372 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3373 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3374 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3375 MatCheckPreallocated(mat, 1); 3376 if (!info) { 3377 PetscCall(MatFactorInfoInitialize(&tinfo)); 3378 info = &tinfo; 3379 } 3380 3381 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3382 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3383 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3384 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3385 PetscFunctionReturn(PETSC_SUCCESS); 3386 } 3387 3388 /*@ 3389 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3390 of a symmetric matrix. 3391 3392 Collective 3393 3394 Input Parameters: 3395 + fact - the factor matrix obtained with `MatGetFactor()` 3396 . mat - the matrix 3397 . perm - row and column permutations 3398 - info - options for factorization, includes 3399 .vb 3400 fill - expected fill as ratio of original fill. 3401 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3402 Run with the option -info to determine an optimal value to use 3403 .ve 3404 3405 Level: developer 3406 3407 Notes: 3408 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3409 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3410 3411 Most users should employ the `KSP` interface for linear solvers 3412 instead of working directly with matrix algebra routines such as this. 3413 See, e.g., `KSPCreate()`. 3414 3415 Developer Note: 3416 The Fortran interface is not autogenerated as the 3417 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3418 3419 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3420 `MatGetOrdering()` 3421 @*/ 3422 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3423 { 3424 MatFactorInfo tinfo; 3425 3426 PetscFunctionBegin; 3427 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3428 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3429 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3430 if (info) PetscAssertPointer(info, 4); 3431 PetscValidType(fact, 1); 3432 PetscValidType(mat, 2); 3433 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3434 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3435 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3436 MatCheckPreallocated(mat, 2); 3437 if (!info) { 3438 PetscCall(MatFactorInfoInitialize(&tinfo)); 3439 info = &tinfo; 3440 } 3441 3442 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3443 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3444 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3445 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3446 PetscFunctionReturn(PETSC_SUCCESS); 3447 } 3448 3449 /*@ 3450 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3451 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3452 `MatCholeskyFactorSymbolic()`. 3453 3454 Collective 3455 3456 Input Parameters: 3457 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3458 . mat - the initial matrix that is to be factored 3459 - info - options for factorization 3460 3461 Level: developer 3462 3463 Note: 3464 Most users should employ the `KSP` interface for linear solvers 3465 instead of working directly with matrix algebra routines such as this. 3466 See, e.g., `KSPCreate()`. 3467 3468 Developer Note: 3469 The Fortran interface is not autogenerated as the 3470 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3471 3472 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3473 @*/ 3474 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3475 { 3476 MatFactorInfo tinfo; 3477 3478 PetscFunctionBegin; 3479 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3480 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3481 PetscValidType(fact, 1); 3482 PetscValidType(mat, 2); 3483 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3484 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, 3485 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3486 MatCheckPreallocated(mat, 2); 3487 if (!info) { 3488 PetscCall(MatFactorInfoInitialize(&tinfo)); 3489 info = &tinfo; 3490 } 3491 3492 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3493 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3494 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3495 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3496 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3497 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3498 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3499 PetscFunctionReturn(PETSC_SUCCESS); 3500 } 3501 3502 /*@ 3503 MatQRFactor - Performs in-place QR factorization of matrix. 3504 3505 Collective 3506 3507 Input Parameters: 3508 + mat - the matrix 3509 . col - column permutation 3510 - info - options for factorization, includes 3511 .vb 3512 fill - expected fill as ratio of original fill. 3513 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3514 Run with the option -info to determine an optimal value to use 3515 .ve 3516 3517 Level: developer 3518 3519 Notes: 3520 Most users should employ the `KSP` interface for linear solvers 3521 instead of working directly with matrix algebra routines such as this. 3522 See, e.g., `KSPCreate()`. 3523 3524 This changes the state of the matrix to a factored matrix; it cannot be used 3525 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3526 3527 Developer Note: 3528 The Fortran interface is not autogenerated as the 3529 interface definition cannot be generated correctly [due to MatFactorInfo] 3530 3531 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3532 `MatSetUnfactored()` 3533 @*/ 3534 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3535 { 3536 PetscFunctionBegin; 3537 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3538 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3539 if (info) PetscAssertPointer(info, 3); 3540 PetscValidType(mat, 1); 3541 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3542 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3543 MatCheckPreallocated(mat, 1); 3544 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3545 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3546 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3547 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3548 PetscFunctionReturn(PETSC_SUCCESS); 3549 } 3550 3551 /*@ 3552 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3553 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3554 3555 Collective 3556 3557 Input Parameters: 3558 + fact - the factor matrix obtained with `MatGetFactor()` 3559 . mat - the matrix 3560 . col - column permutation 3561 - info - options for factorization, includes 3562 .vb 3563 fill - expected fill as ratio of original fill. 3564 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3565 Run with the option -info to determine an optimal value to use 3566 .ve 3567 3568 Level: developer 3569 3570 Note: 3571 Most users should employ the `KSP` interface for linear solvers 3572 instead of working directly with matrix algebra routines such as this. 3573 See, e.g., `KSPCreate()`. 3574 3575 Developer Note: 3576 The Fortran interface is not autogenerated as the 3577 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3578 3579 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3580 @*/ 3581 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3582 { 3583 MatFactorInfo tinfo; 3584 3585 PetscFunctionBegin; 3586 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3588 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3589 if (info) PetscAssertPointer(info, 4); 3590 PetscValidType(fact, 1); 3591 PetscValidType(mat, 2); 3592 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3593 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3594 MatCheckPreallocated(mat, 2); 3595 if (!info) { 3596 PetscCall(MatFactorInfoInitialize(&tinfo)); 3597 info = &tinfo; 3598 } 3599 3600 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3601 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3602 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3603 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3604 PetscFunctionReturn(PETSC_SUCCESS); 3605 } 3606 3607 /*@ 3608 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3609 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3610 3611 Collective 3612 3613 Input Parameters: 3614 + fact - the factor matrix obtained with `MatGetFactor()` 3615 . mat - the matrix 3616 - info - options for factorization 3617 3618 Level: developer 3619 3620 Notes: 3621 See `MatQRFactor()` for in-place factorization. 3622 3623 Most users should employ the `KSP` interface for linear solvers 3624 instead of working directly with matrix algebra routines such as this. 3625 See, e.g., `KSPCreate()`. 3626 3627 Developer Note: 3628 The Fortran interface is not autogenerated as the 3629 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3630 3631 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3632 @*/ 3633 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3634 { 3635 MatFactorInfo tinfo; 3636 3637 PetscFunctionBegin; 3638 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3639 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3640 PetscValidType(fact, 1); 3641 PetscValidType(mat, 2); 3642 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3643 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, 3644 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3645 3646 MatCheckPreallocated(mat, 2); 3647 if (!info) { 3648 PetscCall(MatFactorInfoInitialize(&tinfo)); 3649 info = &tinfo; 3650 } 3651 3652 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3653 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3654 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3655 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3656 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3657 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3658 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3659 PetscFunctionReturn(PETSC_SUCCESS); 3660 } 3661 3662 /*@ 3663 MatSolve - Solves $A x = b$, given a factored matrix. 3664 3665 Neighbor-wise Collective 3666 3667 Input Parameters: 3668 + mat - the factored matrix 3669 - b - the right-hand-side vector 3670 3671 Output Parameter: 3672 . x - the result vector 3673 3674 Level: developer 3675 3676 Notes: 3677 The vectors `b` and `x` cannot be the same. I.e., one cannot 3678 call `MatSolve`(A,x,x). 3679 3680 Most users should employ the `KSP` interface for linear solvers 3681 instead of working directly with matrix algebra routines such as this. 3682 See, e.g., `KSPCreate()`. 3683 3684 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3685 @*/ 3686 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3687 { 3688 PetscFunctionBegin; 3689 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3690 PetscValidType(mat, 1); 3691 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3692 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3693 PetscCheckSameComm(mat, 1, b, 2); 3694 PetscCheckSameComm(mat, 1, x, 3); 3695 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3696 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); 3697 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); 3698 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); 3699 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3700 MatCheckPreallocated(mat, 1); 3701 3702 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3703 PetscCall(VecFlag(x, mat->factorerrortype)); 3704 if (mat->factorerrortype) { 3705 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3706 } else PetscUseTypeMethod(mat, solve, b, x); 3707 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3708 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3709 PetscFunctionReturn(PETSC_SUCCESS); 3710 } 3711 3712 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3713 { 3714 Vec b, x; 3715 PetscInt N, i; 3716 PetscErrorCode (*f)(Mat, Vec, Vec); 3717 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3718 3719 PetscFunctionBegin; 3720 if (A->factorerrortype) { 3721 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3722 PetscCall(MatSetInf(X)); 3723 PetscFunctionReturn(PETSC_SUCCESS); 3724 } 3725 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3726 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3727 PetscCall(MatBoundToCPU(A, &Abound)); 3728 if (!Abound) { 3729 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3730 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3731 } 3732 #if PetscDefined(HAVE_CUDA) 3733 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3734 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3735 #elif PetscDefined(HAVE_HIP) 3736 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3737 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3738 #endif 3739 PetscCall(MatGetSize(B, NULL, &N)); 3740 for (i = 0; i < N; i++) { 3741 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3742 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3743 PetscCall((*f)(A, b, x)); 3744 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3745 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3746 } 3747 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3748 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3749 PetscFunctionReturn(PETSC_SUCCESS); 3750 } 3751 3752 /*@ 3753 MatMatSolve - Solves $A X = B$, given a factored matrix. 3754 3755 Neighbor-wise Collective 3756 3757 Input Parameters: 3758 + A - the factored matrix 3759 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3760 3761 Output Parameter: 3762 . X - the result matrix (dense matrix) 3763 3764 Level: developer 3765 3766 Note: 3767 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3768 otherwise, `B` and `X` cannot be the same. 3769 3770 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3771 @*/ 3772 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3773 { 3774 PetscFunctionBegin; 3775 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3776 PetscValidType(A, 1); 3777 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3778 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3779 PetscCheckSameComm(A, 1, B, 2); 3780 PetscCheckSameComm(A, 1, X, 3); 3781 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); 3782 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); 3783 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"); 3784 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3785 MatCheckPreallocated(A, 1); 3786 3787 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3788 if (!A->ops->matsolve) { 3789 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3790 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3791 } else PetscUseTypeMethod(A, matsolve, B, X); 3792 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3793 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3794 PetscFunctionReturn(PETSC_SUCCESS); 3795 } 3796 3797 /*@ 3798 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3799 3800 Neighbor-wise Collective 3801 3802 Input Parameters: 3803 + A - the factored matrix 3804 - B - the right-hand-side matrix (`MATDENSE` matrix) 3805 3806 Output Parameter: 3807 . X - the result matrix (dense matrix) 3808 3809 Level: developer 3810 3811 Note: 3812 The matrices `B` and `X` cannot be the same. I.e., one cannot 3813 call `MatMatSolveTranspose`(A,X,X). 3814 3815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3816 @*/ 3817 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3818 { 3819 PetscFunctionBegin; 3820 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3821 PetscValidType(A, 1); 3822 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3823 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3824 PetscCheckSameComm(A, 1, B, 2); 3825 PetscCheckSameComm(A, 1, X, 3); 3826 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3827 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); 3828 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); 3829 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); 3830 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"); 3831 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3832 MatCheckPreallocated(A, 1); 3833 3834 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3835 if (!A->ops->matsolvetranspose) { 3836 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3837 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3838 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3839 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3840 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3841 PetscFunctionReturn(PETSC_SUCCESS); 3842 } 3843 3844 /*@ 3845 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3846 3847 Neighbor-wise Collective 3848 3849 Input Parameters: 3850 + A - the factored matrix 3851 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3852 3853 Output Parameter: 3854 . X - the result matrix (dense matrix) 3855 3856 Level: developer 3857 3858 Note: 3859 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 3860 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3861 3862 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3863 @*/ 3864 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3865 { 3866 PetscFunctionBegin; 3867 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3868 PetscValidType(A, 1); 3869 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3870 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3871 PetscCheckSameComm(A, 1, Bt, 2); 3872 PetscCheckSameComm(A, 1, X, 3); 3873 3874 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3875 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); 3876 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); 3877 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"); 3878 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3879 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3880 MatCheckPreallocated(A, 1); 3881 3882 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3883 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3884 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3885 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3886 PetscFunctionReturn(PETSC_SUCCESS); 3887 } 3888 3889 /*@ 3890 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3891 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3892 3893 Neighbor-wise Collective 3894 3895 Input Parameters: 3896 + mat - the factored matrix 3897 - b - the right-hand-side vector 3898 3899 Output Parameter: 3900 . x - the result vector 3901 3902 Level: developer 3903 3904 Notes: 3905 `MatSolve()` should be used for most applications, as it performs 3906 a forward solve followed by a backward solve. 3907 3908 The vectors `b` and `x` cannot be the same, i.e., one cannot 3909 call `MatForwardSolve`(A,x,x). 3910 3911 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3912 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3913 `MatForwardSolve()` solves $U^T*D y = b$, and 3914 `MatBackwardSolve()` solves $U x = y$. 3915 Thus they do not provide a symmetric preconditioner. 3916 3917 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3918 @*/ 3919 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3920 { 3921 PetscFunctionBegin; 3922 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3923 PetscValidType(mat, 1); 3924 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3925 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3926 PetscCheckSameComm(mat, 1, b, 2); 3927 PetscCheckSameComm(mat, 1, x, 3); 3928 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3929 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); 3930 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); 3931 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); 3932 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3933 MatCheckPreallocated(mat, 1); 3934 3935 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3936 PetscUseTypeMethod(mat, forwardsolve, b, x); 3937 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3938 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3939 PetscFunctionReturn(PETSC_SUCCESS); 3940 } 3941 3942 /*@ 3943 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3944 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3945 3946 Neighbor-wise Collective 3947 3948 Input Parameters: 3949 + mat - the factored matrix 3950 - b - the right-hand-side vector 3951 3952 Output Parameter: 3953 . x - the result vector 3954 3955 Level: developer 3956 3957 Notes: 3958 `MatSolve()` should be used for most applications, as it performs 3959 a forward solve followed by a backward solve. 3960 3961 The vectors `b` and `x` cannot be the same. I.e., one cannot 3962 call `MatBackwardSolve`(A,x,x). 3963 3964 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3965 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3966 `MatForwardSolve()` solves $U^T*D y = b$, and 3967 `MatBackwardSolve()` solves $U x = y$. 3968 Thus they do not provide a symmetric preconditioner. 3969 3970 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3971 @*/ 3972 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3973 { 3974 PetscFunctionBegin; 3975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3976 PetscValidType(mat, 1); 3977 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3978 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3979 PetscCheckSameComm(mat, 1, b, 2); 3980 PetscCheckSameComm(mat, 1, x, 3); 3981 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3982 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); 3983 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); 3984 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); 3985 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3986 MatCheckPreallocated(mat, 1); 3987 3988 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3989 PetscUseTypeMethod(mat, backwardsolve, b, x); 3990 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3991 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3992 PetscFunctionReturn(PETSC_SUCCESS); 3993 } 3994 3995 /*@ 3996 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3997 3998 Neighbor-wise Collective 3999 4000 Input Parameters: 4001 + mat - the factored matrix 4002 . b - the right-hand-side vector 4003 - y - the vector to be added to 4004 4005 Output Parameter: 4006 . x - the result vector 4007 4008 Level: developer 4009 4010 Note: 4011 The vectors `b` and `x` cannot be the same. I.e., one cannot 4012 call `MatSolveAdd`(A,x,y,x). 4013 4014 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4015 @*/ 4016 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4017 { 4018 PetscScalar one = 1.0; 4019 Vec tmp; 4020 4021 PetscFunctionBegin; 4022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4023 PetscValidType(mat, 1); 4024 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4025 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4026 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4027 PetscCheckSameComm(mat, 1, b, 2); 4028 PetscCheckSameComm(mat, 1, y, 3); 4029 PetscCheckSameComm(mat, 1, x, 4); 4030 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4031 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); 4032 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); 4033 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); 4034 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); 4035 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); 4036 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4037 MatCheckPreallocated(mat, 1); 4038 4039 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4040 PetscCall(VecFlag(x, mat->factorerrortype)); 4041 if (mat->factorerrortype) { 4042 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4043 } else if (mat->ops->solveadd) { 4044 PetscUseTypeMethod(mat, solveadd, b, y, x); 4045 } else { 4046 /* do the solve then the add manually */ 4047 if (x != y) { 4048 PetscCall(MatSolve(mat, b, x)); 4049 PetscCall(VecAXPY(x, one, y)); 4050 } else { 4051 PetscCall(VecDuplicate(x, &tmp)); 4052 PetscCall(VecCopy(x, tmp)); 4053 PetscCall(MatSolve(mat, b, x)); 4054 PetscCall(VecAXPY(x, one, tmp)); 4055 PetscCall(VecDestroy(&tmp)); 4056 } 4057 } 4058 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4059 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4060 PetscFunctionReturn(PETSC_SUCCESS); 4061 } 4062 4063 /*@ 4064 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4065 4066 Neighbor-wise Collective 4067 4068 Input Parameters: 4069 + mat - the factored matrix 4070 - b - the right-hand-side vector 4071 4072 Output Parameter: 4073 . x - the result vector 4074 4075 Level: developer 4076 4077 Notes: 4078 The vectors `b` and `x` cannot be the same. I.e., one cannot 4079 call `MatSolveTranspose`(A,x,x). 4080 4081 Most users should employ the `KSP` interface for linear solvers 4082 instead of working directly with matrix algebra routines such as this. 4083 See, e.g., `KSPCreate()`. 4084 4085 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4086 @*/ 4087 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4088 { 4089 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4090 4091 PetscFunctionBegin; 4092 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4093 PetscValidType(mat, 1); 4094 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4095 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4096 PetscCheckSameComm(mat, 1, b, 2); 4097 PetscCheckSameComm(mat, 1, x, 3); 4098 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4099 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); 4100 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); 4101 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4102 MatCheckPreallocated(mat, 1); 4103 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4104 PetscCall(VecFlag(x, mat->factorerrortype)); 4105 if (mat->factorerrortype) { 4106 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4107 } else { 4108 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4109 PetscCall((*f)(mat, b, x)); 4110 } 4111 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4112 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4113 PetscFunctionReturn(PETSC_SUCCESS); 4114 } 4115 4116 /*@ 4117 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4118 factored matrix. 4119 4120 Neighbor-wise Collective 4121 4122 Input Parameters: 4123 + mat - the factored matrix 4124 . b - the right-hand-side vector 4125 - y - the vector to be added to 4126 4127 Output Parameter: 4128 . x - the result vector 4129 4130 Level: developer 4131 4132 Note: 4133 The vectors `b` and `x` cannot be the same. I.e., one cannot 4134 call `MatSolveTransposeAdd`(A,x,y,x). 4135 4136 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4137 @*/ 4138 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4139 { 4140 PetscScalar one = 1.0; 4141 Vec tmp; 4142 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4143 4144 PetscFunctionBegin; 4145 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4146 PetscValidType(mat, 1); 4147 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4148 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4149 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4150 PetscCheckSameComm(mat, 1, b, 2); 4151 PetscCheckSameComm(mat, 1, y, 3); 4152 PetscCheckSameComm(mat, 1, x, 4); 4153 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4154 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); 4155 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); 4156 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); 4157 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); 4158 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4159 MatCheckPreallocated(mat, 1); 4160 4161 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4162 PetscCall(VecFlag(x, mat->factorerrortype)); 4163 if (mat->factorerrortype) { 4164 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4165 } else if (f) { 4166 PetscCall((*f)(mat, b, y, x)); 4167 } else { 4168 /* do the solve then the add manually */ 4169 if (x != y) { 4170 PetscCall(MatSolveTranspose(mat, b, x)); 4171 PetscCall(VecAXPY(x, one, y)); 4172 } else { 4173 PetscCall(VecDuplicate(x, &tmp)); 4174 PetscCall(VecCopy(x, tmp)); 4175 PetscCall(MatSolveTranspose(mat, b, x)); 4176 PetscCall(VecAXPY(x, one, tmp)); 4177 PetscCall(VecDestroy(&tmp)); 4178 } 4179 } 4180 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4181 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4182 PetscFunctionReturn(PETSC_SUCCESS); 4183 } 4184 4185 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4186 /*@ 4187 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4188 4189 Neighbor-wise Collective 4190 4191 Input Parameters: 4192 + mat - the matrix 4193 . b - the right-hand side 4194 . omega - the relaxation factor 4195 . flag - flag indicating the type of SOR (see below) 4196 . shift - diagonal shift 4197 . its - the number of iterations 4198 - lits - the number of local iterations 4199 4200 Output Parameter: 4201 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4202 4203 SOR Flags: 4204 + `SOR_FORWARD_SWEEP` - forward SOR 4205 . `SOR_BACKWARD_SWEEP` - backward SOR 4206 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4207 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4208 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4209 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4210 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4211 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4212 upper/lower triangular part of matrix to 4213 vector (with omega) 4214 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4215 4216 Level: developer 4217 4218 Notes: 4219 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4220 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4221 on each processor. 4222 4223 Application programmers will not generally use `MatSOR()` directly, 4224 but instead will employ the `KSP`/`PC` interface. 4225 4226 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4227 4228 Most users should employ the `KSP` interface for linear solvers 4229 instead of working directly with matrix algebra routines such as this. 4230 See, e.g., `KSPCreate()`. 4231 4232 Vectors `x` and `b` CANNOT be the same 4233 4234 The flags are implemented as bitwise inclusive or operations. 4235 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4236 to specify a zero initial guess for SSOR. 4237 4238 Developer Note: 4239 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4240 4241 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4242 @*/ 4243 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4244 { 4245 PetscFunctionBegin; 4246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4247 PetscValidType(mat, 1); 4248 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4249 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4250 PetscCheckSameComm(mat, 1, b, 2); 4251 PetscCheckSameComm(mat, 1, x, 8); 4252 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4253 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4254 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); 4255 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); 4256 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); 4257 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4258 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4259 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4260 4261 MatCheckPreallocated(mat, 1); 4262 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4263 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4264 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4265 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4266 PetscFunctionReturn(PETSC_SUCCESS); 4267 } 4268 4269 /* 4270 Default matrix copy routine. 4271 */ 4272 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4273 { 4274 PetscInt i, rstart = 0, rend = 0, nz; 4275 const PetscInt *cwork; 4276 const PetscScalar *vwork; 4277 4278 PetscFunctionBegin; 4279 if (B->assembled) PetscCall(MatZeroEntries(B)); 4280 if (str == SAME_NONZERO_PATTERN) { 4281 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4282 for (i = rstart; i < rend; i++) { 4283 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4284 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4285 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4286 } 4287 } else { 4288 PetscCall(MatAYPX(B, 0.0, A, str)); 4289 } 4290 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4291 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4292 PetscFunctionReturn(PETSC_SUCCESS); 4293 } 4294 4295 /*@ 4296 MatCopy - Copies a matrix to another matrix. 4297 4298 Collective 4299 4300 Input Parameters: 4301 + A - the matrix 4302 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4303 4304 Output Parameter: 4305 . B - where the copy is put 4306 4307 Level: intermediate 4308 4309 Notes: 4310 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4311 4312 `MatCopy()` copies the matrix entries of a matrix to another existing 4313 matrix (after first zeroing the second matrix). A related routine is 4314 `MatConvert()`, which first creates a new matrix and then copies the data. 4315 4316 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4317 @*/ 4318 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4319 { 4320 PetscInt i; 4321 4322 PetscFunctionBegin; 4323 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4324 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4325 PetscValidType(A, 1); 4326 PetscValidType(B, 2); 4327 PetscCheckSameComm(A, 1, B, 2); 4328 MatCheckPreallocated(B, 2); 4329 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4330 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4331 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, 4332 A->cmap->N, B->cmap->N); 4333 MatCheckPreallocated(A, 1); 4334 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4335 4336 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4337 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4338 else PetscCall(MatCopy_Basic(A, B, str)); 4339 4340 B->stencil.dim = A->stencil.dim; 4341 B->stencil.noc = A->stencil.noc; 4342 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4343 B->stencil.dims[i] = A->stencil.dims[i]; 4344 B->stencil.starts[i] = A->stencil.starts[i]; 4345 } 4346 4347 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4348 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4349 PetscFunctionReturn(PETSC_SUCCESS); 4350 } 4351 4352 /*@ 4353 MatConvert - Converts a matrix to another matrix, either of the same 4354 or different type. 4355 4356 Collective 4357 4358 Input Parameters: 4359 + mat - the matrix 4360 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4361 same type as the original matrix. 4362 - reuse - denotes if the destination matrix is to be created or reused. 4363 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 4364 `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). 4365 4366 Output Parameter: 4367 . M - pointer to place new matrix 4368 4369 Level: intermediate 4370 4371 Notes: 4372 `MatConvert()` first creates a new matrix and then copies the data from 4373 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4374 entries of one matrix to another already existing matrix context. 4375 4376 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4377 the MPI communicator of the generated matrix is always the same as the communicator 4378 of the input matrix. 4379 4380 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4381 @*/ 4382 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4383 { 4384 PetscBool sametype, issame, flg; 4385 PetscBool3 issymmetric, ishermitian; 4386 char convname[256], mtype[256]; 4387 Mat B; 4388 4389 PetscFunctionBegin; 4390 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4391 PetscValidType(mat, 1); 4392 PetscAssertPointer(M, 4); 4393 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4394 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4395 MatCheckPreallocated(mat, 1); 4396 4397 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4398 if (flg) newtype = mtype; 4399 4400 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4401 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4402 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4403 if (reuse == MAT_REUSE_MATRIX) { 4404 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4405 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4406 } 4407 4408 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4409 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4410 PetscFunctionReturn(PETSC_SUCCESS); 4411 } 4412 4413 /* Cache Mat options because some converters use MatHeaderReplace */ 4414 issymmetric = mat->symmetric; 4415 ishermitian = mat->hermitian; 4416 4417 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4418 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4419 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4420 } else { 4421 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4422 const char *prefix[3] = {"seq", "mpi", ""}; 4423 PetscInt i; 4424 /* 4425 Order of precedence: 4426 0) See if newtype is a superclass of the current matrix. 4427 1) See if a specialized converter is known to the current matrix. 4428 2) See if a specialized converter is known to the desired matrix class. 4429 3) See if a good general converter is registered for the desired class 4430 (as of 6/27/03 only MATMPIADJ falls into this category). 4431 4) See if a good general converter is known for the current matrix. 4432 5) Use a really basic converter. 4433 */ 4434 4435 /* 0) See if newtype is a superclass of the current matrix. 4436 i.e mat is mpiaij and newtype is aij */ 4437 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4438 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4439 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4440 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4441 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4442 if (flg) { 4443 if (reuse == MAT_INPLACE_MATRIX) { 4444 PetscCall(PetscInfo(mat, "Early return\n")); 4445 PetscFunctionReturn(PETSC_SUCCESS); 4446 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4447 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4448 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4449 PetscFunctionReturn(PETSC_SUCCESS); 4450 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4451 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4452 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4453 PetscFunctionReturn(PETSC_SUCCESS); 4454 } 4455 } 4456 } 4457 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4458 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4459 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4460 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4461 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4462 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4463 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4464 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4465 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4466 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4467 if (conv) goto foundconv; 4468 } 4469 4470 /* 2) See if a specialized converter is known to the desired matrix class. */ 4471 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4472 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4473 PetscCall(MatSetType(B, newtype)); 4474 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4475 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4476 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4477 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4478 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4479 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4480 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4481 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4482 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4483 if (conv) { 4484 PetscCall(MatDestroy(&B)); 4485 goto foundconv; 4486 } 4487 } 4488 4489 /* 3) See if a good general converter is registered for the desired class */ 4490 conv = B->ops->convertfrom; 4491 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4492 PetscCall(MatDestroy(&B)); 4493 if (conv) goto foundconv; 4494 4495 /* 4) See if a good general converter is known for the current matrix */ 4496 if (mat->ops->convert) conv = mat->ops->convert; 4497 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4498 if (conv) goto foundconv; 4499 4500 /* 5) Use a really basic converter. */ 4501 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4502 conv = MatConvert_Basic; 4503 4504 foundconv: 4505 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4506 PetscCall((*conv)(mat, newtype, reuse, M)); 4507 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4508 /* the block sizes must be same if the mappings are copied over */ 4509 (*M)->rmap->bs = mat->rmap->bs; 4510 (*M)->cmap->bs = mat->cmap->bs; 4511 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4512 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4513 (*M)->rmap->mapping = mat->rmap->mapping; 4514 (*M)->cmap->mapping = mat->cmap->mapping; 4515 } 4516 (*M)->stencil.dim = mat->stencil.dim; 4517 (*M)->stencil.noc = mat->stencil.noc; 4518 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4519 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4520 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4521 } 4522 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4523 } 4524 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4525 4526 /* Copy Mat options */ 4527 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4528 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4529 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4530 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4531 PetscFunctionReturn(PETSC_SUCCESS); 4532 } 4533 4534 /*@ 4535 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4536 4537 Not Collective 4538 4539 Input Parameter: 4540 . mat - the matrix, must be a factored matrix 4541 4542 Output Parameter: 4543 . type - the string name of the package (do not free this string) 4544 4545 Level: intermediate 4546 4547 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4548 @*/ 4549 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4550 { 4551 PetscErrorCode (*conv)(Mat, MatSolverType *); 4552 4553 PetscFunctionBegin; 4554 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4555 PetscValidType(mat, 1); 4556 PetscAssertPointer(type, 2); 4557 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4558 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4559 if (conv) PetscCall((*conv)(mat, type)); 4560 else *type = MATSOLVERPETSC; 4561 PetscFunctionReturn(PETSC_SUCCESS); 4562 } 4563 4564 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4565 struct _MatSolverTypeForSpecifcType { 4566 MatType mtype; 4567 /* no entry for MAT_FACTOR_NONE */ 4568 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4569 MatSolverTypeForSpecifcType next; 4570 }; 4571 4572 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4573 struct _MatSolverTypeHolder { 4574 char *name; 4575 MatSolverTypeForSpecifcType handlers; 4576 MatSolverTypeHolder next; 4577 }; 4578 4579 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4580 4581 /*@C 4582 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4583 4584 Logically Collective, No Fortran Support 4585 4586 Input Parameters: 4587 + package - name of the package, for example `petsc` or `superlu` 4588 . mtype - the matrix type that works with this package 4589 . ftype - the type of factorization supported by the package 4590 - createfactor - routine that will create the factored matrix ready to be used 4591 4592 Level: developer 4593 4594 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4595 `MatGetFactor()` 4596 @*/ 4597 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4598 { 4599 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4600 PetscBool flg; 4601 MatSolverTypeForSpecifcType inext, iprev = NULL; 4602 4603 PetscFunctionBegin; 4604 PetscCall(MatInitializePackage()); 4605 if (!next) { 4606 PetscCall(PetscNew(&MatSolverTypeHolders)); 4607 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4608 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4609 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4610 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4611 PetscFunctionReturn(PETSC_SUCCESS); 4612 } 4613 while (next) { 4614 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4615 if (flg) { 4616 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4617 inext = next->handlers; 4618 while (inext) { 4619 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4620 if (flg) { 4621 inext->createfactor[(int)ftype - 1] = createfactor; 4622 PetscFunctionReturn(PETSC_SUCCESS); 4623 } 4624 iprev = inext; 4625 inext = inext->next; 4626 } 4627 PetscCall(PetscNew(&iprev->next)); 4628 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4629 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4630 PetscFunctionReturn(PETSC_SUCCESS); 4631 } 4632 prev = next; 4633 next = next->next; 4634 } 4635 PetscCall(PetscNew(&prev->next)); 4636 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4637 PetscCall(PetscNew(&prev->next->handlers)); 4638 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4639 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4640 PetscFunctionReturn(PETSC_SUCCESS); 4641 } 4642 4643 /*@C 4644 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4645 4646 Input Parameters: 4647 + 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 4648 . ftype - the type of factorization supported by the type 4649 - mtype - the matrix type that works with this type 4650 4651 Output Parameters: 4652 + foundtype - `PETSC_TRUE` if the type was registered 4653 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4654 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4655 4656 Calling sequence of `createfactor`: 4657 + A - the matrix providing the factor matrix 4658 . ftype - the `MatFactorType` of the factor requested 4659 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4660 4661 Level: developer 4662 4663 Note: 4664 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4665 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4666 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4667 4668 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4669 `MatInitializePackage()` 4670 @*/ 4671 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4672 { 4673 MatSolverTypeHolder next = MatSolverTypeHolders; 4674 PetscBool flg; 4675 MatSolverTypeForSpecifcType inext; 4676 4677 PetscFunctionBegin; 4678 if (foundtype) *foundtype = PETSC_FALSE; 4679 if (foundmtype) *foundmtype = PETSC_FALSE; 4680 if (createfactor) *createfactor = NULL; 4681 4682 if (type) { 4683 while (next) { 4684 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4685 if (flg) { 4686 if (foundtype) *foundtype = PETSC_TRUE; 4687 inext = next->handlers; 4688 while (inext) { 4689 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4690 if (flg) { 4691 if (foundmtype) *foundmtype = PETSC_TRUE; 4692 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4693 PetscFunctionReturn(PETSC_SUCCESS); 4694 } 4695 inext = inext->next; 4696 } 4697 } 4698 next = next->next; 4699 } 4700 } else { 4701 while (next) { 4702 inext = next->handlers; 4703 while (inext) { 4704 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4705 if (flg && inext->createfactor[(int)ftype - 1]) { 4706 if (foundtype) *foundtype = PETSC_TRUE; 4707 if (foundmtype) *foundmtype = PETSC_TRUE; 4708 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4709 PetscFunctionReturn(PETSC_SUCCESS); 4710 } 4711 inext = inext->next; 4712 } 4713 next = next->next; 4714 } 4715 /* try with base classes inext->mtype */ 4716 next = MatSolverTypeHolders; 4717 while (next) { 4718 inext = next->handlers; 4719 while (inext) { 4720 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4721 if (flg && inext->createfactor[(int)ftype - 1]) { 4722 if (foundtype) *foundtype = PETSC_TRUE; 4723 if (foundmtype) *foundmtype = PETSC_TRUE; 4724 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4725 PetscFunctionReturn(PETSC_SUCCESS); 4726 } 4727 inext = inext->next; 4728 } 4729 next = next->next; 4730 } 4731 } 4732 PetscFunctionReturn(PETSC_SUCCESS); 4733 } 4734 4735 PetscErrorCode MatSolverTypeDestroy(void) 4736 { 4737 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4738 MatSolverTypeForSpecifcType inext, iprev; 4739 4740 PetscFunctionBegin; 4741 while (next) { 4742 PetscCall(PetscFree(next->name)); 4743 inext = next->handlers; 4744 while (inext) { 4745 PetscCall(PetscFree(inext->mtype)); 4746 iprev = inext; 4747 inext = inext->next; 4748 PetscCall(PetscFree(iprev)); 4749 } 4750 prev = next; 4751 next = next->next; 4752 PetscCall(PetscFree(prev)); 4753 } 4754 MatSolverTypeHolders = NULL; 4755 PetscFunctionReturn(PETSC_SUCCESS); 4756 } 4757 4758 /*@ 4759 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4760 4761 Logically Collective 4762 4763 Input Parameter: 4764 . mat - the matrix 4765 4766 Output Parameter: 4767 . flg - `PETSC_TRUE` if uses the ordering 4768 4769 Level: developer 4770 4771 Note: 4772 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4773 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4774 4775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4776 @*/ 4777 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4778 { 4779 PetscFunctionBegin; 4780 *flg = mat->canuseordering; 4781 PetscFunctionReturn(PETSC_SUCCESS); 4782 } 4783 4784 /*@ 4785 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4786 4787 Logically Collective 4788 4789 Input Parameters: 4790 + mat - the matrix obtained with `MatGetFactor()` 4791 - ftype - the factorization type to be used 4792 4793 Output Parameter: 4794 . otype - the preferred ordering type 4795 4796 Level: developer 4797 4798 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4799 @*/ 4800 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4801 { 4802 PetscFunctionBegin; 4803 *otype = mat->preferredordering[ftype]; 4804 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4805 PetscFunctionReturn(PETSC_SUCCESS); 4806 } 4807 4808 /*@ 4809 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4810 4811 Collective 4812 4813 Input Parameters: 4814 + mat - the matrix 4815 . 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 4816 the other criteria is returned 4817 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4818 4819 Output Parameter: 4820 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4821 4822 Options Database Keys: 4823 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4824 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4825 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4826 4827 Level: intermediate 4828 4829 Notes: 4830 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4831 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4832 4833 Users usually access the factorization solvers via `KSP` 4834 4835 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4836 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 4837 4838 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4839 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4840 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4841 4842 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4843 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4844 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4845 4846 Developer Note: 4847 This should actually be called `MatCreateFactor()` since it creates a new factor object 4848 4849 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4850 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4851 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4852 @*/ 4853 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4854 { 4855 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4856 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4857 4858 PetscFunctionBegin; 4859 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4860 PetscValidType(mat, 1); 4861 4862 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4863 MatCheckPreallocated(mat, 1); 4864 4865 PetscCall(MatIsShell(mat, &shell)); 4866 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4867 if (hasop) { 4868 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4869 PetscFunctionReturn(PETSC_SUCCESS); 4870 } 4871 4872 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4873 if (!foundtype) { 4874 if (type) { 4875 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], 4876 ((PetscObject)mat)->type_name, type); 4877 } else { 4878 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); 4879 } 4880 } 4881 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4882 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); 4883 4884 PetscCall((*conv)(mat, ftype, f)); 4885 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4886 PetscFunctionReturn(PETSC_SUCCESS); 4887 } 4888 4889 /*@ 4890 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4891 4892 Not Collective 4893 4894 Input Parameters: 4895 + mat - the matrix 4896 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4897 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4898 4899 Output Parameter: 4900 . flg - PETSC_TRUE if the factorization is available 4901 4902 Level: intermediate 4903 4904 Notes: 4905 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4906 such as pastix, superlu, mumps etc. 4907 4908 PETSc must have been ./configure to use the external solver, using the option --download-package 4909 4910 Developer Note: 4911 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4912 4913 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4914 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4915 @*/ 4916 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4917 { 4918 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4919 4920 PetscFunctionBegin; 4921 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4922 PetscAssertPointer(flg, 4); 4923 4924 *flg = PETSC_FALSE; 4925 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4926 4927 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4928 MatCheckPreallocated(mat, 1); 4929 4930 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4931 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4932 PetscFunctionReturn(PETSC_SUCCESS); 4933 } 4934 4935 /*@ 4936 MatDuplicate - Duplicates a matrix including the non-zero structure. 4937 4938 Collective 4939 4940 Input Parameters: 4941 + mat - the matrix 4942 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4943 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4944 4945 Output Parameter: 4946 . M - pointer to place new matrix 4947 4948 Level: intermediate 4949 4950 Notes: 4951 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4952 4953 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4954 4955 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. 4956 4957 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4958 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4959 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4960 4961 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4962 @*/ 4963 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4964 { 4965 Mat B; 4966 VecType vtype; 4967 PetscInt i; 4968 PetscObject dm, container_h, container_d; 4969 void (*viewf)(void); 4970 4971 PetscFunctionBegin; 4972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4973 PetscValidType(mat, 1); 4974 PetscAssertPointer(M, 3); 4975 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4976 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4977 MatCheckPreallocated(mat, 1); 4978 4979 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4980 PetscUseTypeMethod(mat, duplicate, op, M); 4981 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4982 B = *M; 4983 4984 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4985 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4986 PetscCall(MatGetVecType(mat, &vtype)); 4987 PetscCall(MatSetVecType(B, vtype)); 4988 4989 B->stencil.dim = mat->stencil.dim; 4990 B->stencil.noc = mat->stencil.noc; 4991 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4992 B->stencil.dims[i] = mat->stencil.dims[i]; 4993 B->stencil.starts[i] = mat->stencil.starts[i]; 4994 } 4995 4996 B->nooffproczerorows = mat->nooffproczerorows; 4997 B->nooffprocentries = mat->nooffprocentries; 4998 4999 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5000 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5001 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5002 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5003 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5004 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5005 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5006 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5007 PetscFunctionReturn(PETSC_SUCCESS); 5008 } 5009 5010 /*@ 5011 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5012 5013 Logically Collective 5014 5015 Input Parameter: 5016 . mat - the matrix 5017 5018 Output Parameter: 5019 . v - the diagonal of the matrix 5020 5021 Level: intermediate 5022 5023 Note: 5024 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5025 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5026 is larger than `ndiag`, the values of the remaining entries are unspecified. 5027 5028 Currently only correct in parallel for square matrices. 5029 5030 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5031 @*/ 5032 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5033 { 5034 PetscFunctionBegin; 5035 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5036 PetscValidType(mat, 1); 5037 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5038 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5039 MatCheckPreallocated(mat, 1); 5040 if (PetscDefined(USE_DEBUG)) { 5041 PetscInt nv, row, col, ndiag; 5042 5043 PetscCall(VecGetLocalSize(v, &nv)); 5044 PetscCall(MatGetLocalSize(mat, &row, &col)); 5045 ndiag = PetscMin(row, col); 5046 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); 5047 } 5048 5049 PetscUseTypeMethod(mat, getdiagonal, v); 5050 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5051 PetscFunctionReturn(PETSC_SUCCESS); 5052 } 5053 5054 /*@ 5055 MatGetRowMin - Gets the minimum value (of the real part) of each 5056 row of the matrix 5057 5058 Logically Collective 5059 5060 Input Parameter: 5061 . mat - the matrix 5062 5063 Output Parameters: 5064 + v - the vector for storing the maximums 5065 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5066 5067 Level: intermediate 5068 5069 Note: 5070 The result of this call are the same as if one converted the matrix to dense format 5071 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5072 5073 This code is only implemented for a couple of matrix formats. 5074 5075 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5076 `MatGetRowMax()` 5077 @*/ 5078 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5079 { 5080 PetscFunctionBegin; 5081 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5082 PetscValidType(mat, 1); 5083 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5084 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5085 5086 if (!mat->cmap->N) { 5087 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5088 if (idx) { 5089 PetscInt i, m = mat->rmap->n; 5090 for (i = 0; i < m; i++) idx[i] = -1; 5091 } 5092 } else { 5093 MatCheckPreallocated(mat, 1); 5094 } 5095 PetscUseTypeMethod(mat, getrowmin, v, idx); 5096 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5097 PetscFunctionReturn(PETSC_SUCCESS); 5098 } 5099 5100 /*@ 5101 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5102 row of the matrix 5103 5104 Logically Collective 5105 5106 Input Parameter: 5107 . mat - the matrix 5108 5109 Output Parameters: 5110 + v - the vector for storing the minimums 5111 - idx - the indices of the column found for each row (or `NULL` if not needed) 5112 5113 Level: intermediate 5114 5115 Notes: 5116 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5117 row is 0 (the first column). 5118 5119 This code is only implemented for a couple of matrix formats. 5120 5121 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5122 @*/ 5123 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5124 { 5125 PetscFunctionBegin; 5126 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5127 PetscValidType(mat, 1); 5128 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5129 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5130 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5131 5132 if (!mat->cmap->N) { 5133 PetscCall(VecSet(v, 0.0)); 5134 if (idx) { 5135 PetscInt i, m = mat->rmap->n; 5136 for (i = 0; i < m; i++) idx[i] = -1; 5137 } 5138 } else { 5139 MatCheckPreallocated(mat, 1); 5140 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5141 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5142 } 5143 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5144 PetscFunctionReturn(PETSC_SUCCESS); 5145 } 5146 5147 /*@ 5148 MatGetRowMax - Gets the maximum value (of the real part) of each 5149 row of the matrix 5150 5151 Logically Collective 5152 5153 Input Parameter: 5154 . mat - the matrix 5155 5156 Output Parameters: 5157 + v - the vector for storing the maximums 5158 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5159 5160 Level: intermediate 5161 5162 Notes: 5163 The result of this call are the same as if one converted the matrix to dense format 5164 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5165 5166 This code is only implemented for a couple of matrix formats. 5167 5168 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5169 @*/ 5170 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5171 { 5172 PetscFunctionBegin; 5173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5174 PetscValidType(mat, 1); 5175 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5176 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5177 5178 if (!mat->cmap->N) { 5179 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5180 if (idx) { 5181 PetscInt i, m = mat->rmap->n; 5182 for (i = 0; i < m; i++) idx[i] = -1; 5183 } 5184 } else { 5185 MatCheckPreallocated(mat, 1); 5186 PetscUseTypeMethod(mat, getrowmax, v, idx); 5187 } 5188 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5189 PetscFunctionReturn(PETSC_SUCCESS); 5190 } 5191 5192 /*@ 5193 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5194 row of the matrix 5195 5196 Logically Collective 5197 5198 Input Parameter: 5199 . mat - the matrix 5200 5201 Output Parameters: 5202 + v - the vector for storing the maximums 5203 - idx - the indices of the column found for each row (or `NULL` if not needed) 5204 5205 Level: intermediate 5206 5207 Notes: 5208 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5209 row is 0 (the first column). 5210 5211 This code is only implemented for a couple of matrix formats. 5212 5213 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5214 @*/ 5215 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5216 { 5217 PetscFunctionBegin; 5218 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5219 PetscValidType(mat, 1); 5220 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5221 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5222 5223 if (!mat->cmap->N) { 5224 PetscCall(VecSet(v, 0.0)); 5225 if (idx) { 5226 PetscInt i, m = mat->rmap->n; 5227 for (i = 0; i < m; i++) idx[i] = -1; 5228 } 5229 } else { 5230 MatCheckPreallocated(mat, 1); 5231 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5232 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5233 } 5234 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5235 PetscFunctionReturn(PETSC_SUCCESS); 5236 } 5237 5238 /*@ 5239 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5240 5241 Logically Collective 5242 5243 Input Parameter: 5244 . mat - the matrix 5245 5246 Output Parameter: 5247 . v - the vector for storing the sum 5248 5249 Level: intermediate 5250 5251 This code is only implemented for a couple of matrix formats. 5252 5253 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5254 @*/ 5255 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5256 { 5257 PetscFunctionBegin; 5258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5259 PetscValidType(mat, 1); 5260 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5262 5263 if (!mat->cmap->N) { 5264 PetscCall(VecSet(v, 0.0)); 5265 } else { 5266 MatCheckPreallocated(mat, 1); 5267 PetscUseTypeMethod(mat, getrowsumabs, v); 5268 } 5269 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5270 PetscFunctionReturn(PETSC_SUCCESS); 5271 } 5272 5273 /*@ 5274 MatGetRowSum - Gets the sum of each row of the matrix 5275 5276 Logically or Neighborhood Collective 5277 5278 Input Parameter: 5279 . mat - the matrix 5280 5281 Output Parameter: 5282 . v - the vector for storing the sum of rows 5283 5284 Level: intermediate 5285 5286 Note: 5287 This code is slow since it is not currently specialized for different formats 5288 5289 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5290 @*/ 5291 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5292 { 5293 Vec ones; 5294 5295 PetscFunctionBegin; 5296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5297 PetscValidType(mat, 1); 5298 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5299 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5300 MatCheckPreallocated(mat, 1); 5301 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5302 PetscCall(VecSet(ones, 1.)); 5303 PetscCall(MatMult(mat, ones, v)); 5304 PetscCall(VecDestroy(&ones)); 5305 PetscFunctionReturn(PETSC_SUCCESS); 5306 } 5307 5308 /*@ 5309 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5310 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5311 5312 Collective 5313 5314 Input Parameter: 5315 . mat - the matrix to provide the transpose 5316 5317 Output Parameter: 5318 . 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 5319 5320 Level: advanced 5321 5322 Note: 5323 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 5324 routine allows bypassing that call. 5325 5326 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5327 @*/ 5328 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5329 { 5330 MatParentState *rb = NULL; 5331 5332 PetscFunctionBegin; 5333 PetscCall(PetscNew(&rb)); 5334 rb->id = ((PetscObject)mat)->id; 5335 rb->state = 0; 5336 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5337 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5338 PetscFunctionReturn(PETSC_SUCCESS); 5339 } 5340 5341 /*@ 5342 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5343 5344 Collective 5345 5346 Input Parameters: 5347 + mat - the matrix to transpose 5348 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5349 5350 Output Parameter: 5351 . B - the transpose of the matrix 5352 5353 Level: intermediate 5354 5355 Notes: 5356 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5357 5358 `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 5359 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5360 5361 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. 5362 5363 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5364 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5365 5366 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5367 5368 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5369 5370 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5371 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5372 @*/ 5373 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5374 { 5375 PetscContainer rB = NULL; 5376 MatParentState *rb = NULL; 5377 5378 PetscFunctionBegin; 5379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5380 PetscValidType(mat, 1); 5381 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5382 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5383 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5384 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5385 MatCheckPreallocated(mat, 1); 5386 if (reuse == MAT_REUSE_MATRIX) { 5387 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5388 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5389 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5390 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5391 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5392 } 5393 5394 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5395 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5396 PetscUseTypeMethod(mat, transpose, reuse, B); 5397 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5398 } 5399 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5400 5401 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5402 if (reuse != MAT_INPLACE_MATRIX) { 5403 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5404 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5405 rb->state = ((PetscObject)mat)->state; 5406 rb->nonzerostate = mat->nonzerostate; 5407 } 5408 PetscFunctionReturn(PETSC_SUCCESS); 5409 } 5410 5411 /*@ 5412 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5413 5414 Collective 5415 5416 Input Parameter: 5417 . A - the matrix to transpose 5418 5419 Output Parameter: 5420 . 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 5421 numerical portion. 5422 5423 Level: intermediate 5424 5425 Note: 5426 This is not supported for many matrix types, use `MatTranspose()` in those cases 5427 5428 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5429 @*/ 5430 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5431 { 5432 PetscFunctionBegin; 5433 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5434 PetscValidType(A, 1); 5435 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5436 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5437 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5438 PetscUseTypeMethod(A, transposesymbolic, B); 5439 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5440 5441 PetscCall(MatTransposeSetPrecursor(A, *B)); 5442 PetscFunctionReturn(PETSC_SUCCESS); 5443 } 5444 5445 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5446 { 5447 PetscContainer rB; 5448 MatParentState *rb; 5449 5450 PetscFunctionBegin; 5451 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5452 PetscValidType(A, 1); 5453 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5454 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5455 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5456 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5457 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5458 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5459 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5460 PetscFunctionReturn(PETSC_SUCCESS); 5461 } 5462 5463 /*@ 5464 MatIsTranspose - Test whether a matrix is another one's transpose, 5465 or its own, in which case it tests symmetry. 5466 5467 Collective 5468 5469 Input Parameters: 5470 + A - the matrix to test 5471 . B - the matrix to test against, this can equal the first parameter 5472 - tol - tolerance, differences between entries smaller than this are counted as zero 5473 5474 Output Parameter: 5475 . flg - the result 5476 5477 Level: intermediate 5478 5479 Notes: 5480 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5481 test involves parallel copies of the block off-diagonal parts of the matrix. 5482 5483 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5484 @*/ 5485 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5486 { 5487 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5488 5489 PetscFunctionBegin; 5490 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5491 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5492 PetscAssertPointer(flg, 4); 5493 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5494 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5495 *flg = PETSC_FALSE; 5496 if (f && g) { 5497 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5498 PetscCall((*f)(A, B, tol, flg)); 5499 } else { 5500 MatType mattype; 5501 5502 PetscCall(MatGetType(f ? B : A, &mattype)); 5503 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5504 } 5505 PetscFunctionReturn(PETSC_SUCCESS); 5506 } 5507 5508 /*@ 5509 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5510 5511 Collective 5512 5513 Input Parameters: 5514 + mat - the matrix to transpose and complex conjugate 5515 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5516 5517 Output Parameter: 5518 . B - the Hermitian transpose 5519 5520 Level: intermediate 5521 5522 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5523 @*/ 5524 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5525 { 5526 PetscFunctionBegin; 5527 PetscCall(MatTranspose(mat, reuse, B)); 5528 #if defined(PETSC_USE_COMPLEX) 5529 PetscCall(MatConjugate(*B)); 5530 #endif 5531 PetscFunctionReturn(PETSC_SUCCESS); 5532 } 5533 5534 /*@ 5535 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5536 5537 Collective 5538 5539 Input Parameters: 5540 + A - the matrix to test 5541 . B - the matrix to test against, this can equal the first parameter 5542 - tol - tolerance, differences between entries smaller than this are counted as zero 5543 5544 Output Parameter: 5545 . flg - the result 5546 5547 Level: intermediate 5548 5549 Notes: 5550 Only available for `MATAIJ` matrices. 5551 5552 The sequential algorithm 5553 has a running time of the order of the number of nonzeros; the parallel 5554 test involves parallel copies of the block off-diagonal parts of the matrix. 5555 5556 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5557 @*/ 5558 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5559 { 5560 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5561 5562 PetscFunctionBegin; 5563 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5564 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5565 PetscAssertPointer(flg, 4); 5566 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5567 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5568 if (f && g) { 5569 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5570 PetscCall((*f)(A, B, tol, flg)); 5571 } 5572 PetscFunctionReturn(PETSC_SUCCESS); 5573 } 5574 5575 /*@ 5576 MatPermute - Creates a new matrix with rows and columns permuted from the 5577 original. 5578 5579 Collective 5580 5581 Input Parameters: 5582 + mat - the matrix to permute 5583 . row - row permutation, each processor supplies only the permutation for its rows 5584 - col - column permutation, each processor supplies only the permutation for its columns 5585 5586 Output Parameter: 5587 . B - the permuted matrix 5588 5589 Level: advanced 5590 5591 Note: 5592 The index sets map from row/col of permuted matrix to row/col of original matrix. 5593 The index sets should be on the same communicator as mat and have the same local sizes. 5594 5595 Developer Note: 5596 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5597 exploit the fact that row and col are permutations, consider implementing the 5598 more general `MatCreateSubMatrix()` instead. 5599 5600 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5601 @*/ 5602 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5603 { 5604 PetscFunctionBegin; 5605 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5606 PetscValidType(mat, 1); 5607 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5608 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5609 PetscAssertPointer(B, 4); 5610 PetscCheckSameComm(mat, 1, row, 2); 5611 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5612 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5613 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5614 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5615 MatCheckPreallocated(mat, 1); 5616 5617 if (mat->ops->permute) { 5618 PetscUseTypeMethod(mat, permute, row, col, B); 5619 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5620 } else { 5621 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5622 } 5623 PetscFunctionReturn(PETSC_SUCCESS); 5624 } 5625 5626 /*@ 5627 MatEqual - Compares two matrices. 5628 5629 Collective 5630 5631 Input Parameters: 5632 + A - the first matrix 5633 - B - the second matrix 5634 5635 Output Parameter: 5636 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5637 5638 Level: intermediate 5639 5640 Note: 5641 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 5642 using several randomly created vectors, see `MatMultEqual()`. 5643 5644 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5645 @*/ 5646 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5647 { 5648 PetscFunctionBegin; 5649 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5650 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5651 PetscValidType(A, 1); 5652 PetscValidType(B, 2); 5653 PetscAssertPointer(flg, 3); 5654 PetscCheckSameComm(A, 1, B, 2); 5655 MatCheckPreallocated(A, 1); 5656 MatCheckPreallocated(B, 2); 5657 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5658 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5659 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, 5660 B->cmap->N); 5661 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5662 PetscUseTypeMethod(A, equal, B, flg); 5663 } else { 5664 PetscCall(MatMultEqual(A, B, 10, flg)); 5665 } 5666 PetscFunctionReturn(PETSC_SUCCESS); 5667 } 5668 5669 /*@ 5670 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5671 matrices that are stored as vectors. Either of the two scaling 5672 matrices can be `NULL`. 5673 5674 Collective 5675 5676 Input Parameters: 5677 + mat - the matrix to be scaled 5678 . l - the left scaling vector (or `NULL`) 5679 - r - the right scaling vector (or `NULL`) 5680 5681 Level: intermediate 5682 5683 Note: 5684 `MatDiagonalScale()` computes $A = LAR$, where 5685 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5686 The L scales the rows of the matrix, the R scales the columns of the matrix. 5687 5688 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5689 @*/ 5690 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5691 { 5692 PetscFunctionBegin; 5693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5694 PetscValidType(mat, 1); 5695 if (l) { 5696 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5697 PetscCheckSameComm(mat, 1, l, 2); 5698 } 5699 if (r) { 5700 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5701 PetscCheckSameComm(mat, 1, r, 3); 5702 } 5703 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5704 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5705 MatCheckPreallocated(mat, 1); 5706 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5707 5708 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5709 PetscUseTypeMethod(mat, diagonalscale, l, r); 5710 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5711 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5712 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5713 PetscFunctionReturn(PETSC_SUCCESS); 5714 } 5715 5716 /*@ 5717 MatScale - Scales all elements of a matrix by a given number. 5718 5719 Logically Collective 5720 5721 Input Parameters: 5722 + mat - the matrix to be scaled 5723 - a - the scaling value 5724 5725 Level: intermediate 5726 5727 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5728 @*/ 5729 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5730 { 5731 PetscFunctionBegin; 5732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5733 PetscValidType(mat, 1); 5734 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5735 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5736 PetscValidLogicalCollectiveScalar(mat, a, 2); 5737 MatCheckPreallocated(mat, 1); 5738 5739 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5740 if (a != (PetscScalar)1.0) { 5741 PetscUseTypeMethod(mat, scale, a); 5742 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5743 } 5744 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5745 PetscFunctionReturn(PETSC_SUCCESS); 5746 } 5747 5748 /*@ 5749 MatNorm - Calculates various norms of a matrix. 5750 5751 Collective 5752 5753 Input Parameters: 5754 + mat - the matrix 5755 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5756 5757 Output Parameter: 5758 . nrm - the resulting norm 5759 5760 Level: intermediate 5761 5762 .seealso: [](ch_matrices), `Mat` 5763 @*/ 5764 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5765 { 5766 PetscFunctionBegin; 5767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5768 PetscValidType(mat, 1); 5769 PetscAssertPointer(nrm, 3); 5770 5771 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5772 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5773 MatCheckPreallocated(mat, 1); 5774 5775 PetscUseTypeMethod(mat, norm, type, nrm); 5776 PetscFunctionReturn(PETSC_SUCCESS); 5777 } 5778 5779 /* 5780 This variable is used to prevent counting of MatAssemblyBegin() that 5781 are called from within a MatAssemblyEnd(). 5782 */ 5783 static PetscInt MatAssemblyEnd_InUse = 0; 5784 /*@ 5785 MatAssemblyBegin - Begins assembling the matrix. This routine should 5786 be called after completing all calls to `MatSetValues()`. 5787 5788 Collective 5789 5790 Input Parameters: 5791 + mat - the matrix 5792 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5793 5794 Level: beginner 5795 5796 Notes: 5797 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5798 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5799 5800 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5801 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5802 using the matrix. 5803 5804 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5805 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 5806 a global collective operation requiring all processes that share the matrix. 5807 5808 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5809 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5810 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5811 5812 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5813 @*/ 5814 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5815 { 5816 PetscFunctionBegin; 5817 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5818 PetscValidType(mat, 1); 5819 MatCheckPreallocated(mat, 1); 5820 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5821 if (mat->assembled) { 5822 mat->was_assembled = PETSC_TRUE; 5823 mat->assembled = PETSC_FALSE; 5824 } 5825 5826 if (!MatAssemblyEnd_InUse) { 5827 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5828 PetscTryTypeMethod(mat, assemblybegin, type); 5829 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5830 } else PetscTryTypeMethod(mat, assemblybegin, type); 5831 PetscFunctionReturn(PETSC_SUCCESS); 5832 } 5833 5834 /*@ 5835 MatAssembled - Indicates if a matrix has been assembled and is ready for 5836 use; for example, in matrix-vector product. 5837 5838 Not Collective 5839 5840 Input Parameter: 5841 . mat - the matrix 5842 5843 Output Parameter: 5844 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5845 5846 Level: advanced 5847 5848 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5849 @*/ 5850 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5851 { 5852 PetscFunctionBegin; 5853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5854 PetscAssertPointer(assembled, 2); 5855 *assembled = mat->assembled; 5856 PetscFunctionReturn(PETSC_SUCCESS); 5857 } 5858 5859 /*@ 5860 MatAssemblyEnd - Completes assembling the matrix. This routine should 5861 be called after `MatAssemblyBegin()`. 5862 5863 Collective 5864 5865 Input Parameters: 5866 + mat - the matrix 5867 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5868 5869 Options Database Keys: 5870 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5871 . -mat_view ::ascii_info_detail - Prints more detailed info 5872 . -mat_view - Prints matrix in ASCII format 5873 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5874 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5875 . -display <name> - Sets display name (default is host) 5876 . -draw_pause <sec> - Sets number of seconds to pause after display 5877 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5878 . -viewer_socket_machine <machine> - Machine to use for socket 5879 . -viewer_socket_port <port> - Port number to use for socket 5880 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5881 5882 Level: beginner 5883 5884 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5885 @*/ 5886 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5887 { 5888 static PetscInt inassm = 0; 5889 PetscBool flg = PETSC_FALSE; 5890 5891 PetscFunctionBegin; 5892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5893 PetscValidType(mat, 1); 5894 5895 inassm++; 5896 MatAssemblyEnd_InUse++; 5897 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5898 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5899 PetscTryTypeMethod(mat, assemblyend, type); 5900 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5901 } else PetscTryTypeMethod(mat, assemblyend, type); 5902 5903 /* Flush assembly is not a true assembly */ 5904 if (type != MAT_FLUSH_ASSEMBLY) { 5905 if (mat->num_ass) { 5906 if (!mat->symmetry_eternal) { 5907 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5908 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5909 } 5910 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5911 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5912 } 5913 mat->num_ass++; 5914 mat->assembled = PETSC_TRUE; 5915 mat->ass_nonzerostate = mat->nonzerostate; 5916 } 5917 5918 mat->insertmode = NOT_SET_VALUES; 5919 MatAssemblyEnd_InUse--; 5920 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5921 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5922 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5923 5924 if (mat->checksymmetryonassembly) { 5925 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5926 if (flg) { 5927 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5928 } else { 5929 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5930 } 5931 } 5932 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5933 } 5934 inassm--; 5935 PetscFunctionReturn(PETSC_SUCCESS); 5936 } 5937 5938 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5939 /*@ 5940 MatSetOption - Sets a parameter option for a matrix. Some options 5941 may be specific to certain storage formats. Some options 5942 determine how values will be inserted (or added). Sorted, 5943 row-oriented input will generally assemble the fastest. The default 5944 is row-oriented. 5945 5946 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5947 5948 Input Parameters: 5949 + mat - the matrix 5950 . op - the option, one of those listed below (and possibly others), 5951 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5952 5953 Options Describing Matrix Structure: 5954 + `MAT_SPD` - symmetric positive definite 5955 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5956 . `MAT_HERMITIAN` - transpose is the complex conjugation 5957 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5958 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5959 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5960 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5961 5962 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5963 do not need to be computed (usually at a high cost) 5964 5965 Options For Use with `MatSetValues()`: 5966 Insert a logically dense subblock, which can be 5967 . `MAT_ROW_ORIENTED` - row-oriented (default) 5968 5969 These options reflect the data you pass in with `MatSetValues()`; it has 5970 nothing to do with how the data is stored internally in the matrix 5971 data structure. 5972 5973 When (re)assembling a matrix, we can restrict the input for 5974 efficiency/debugging purposes. These options include 5975 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5976 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5977 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5978 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5979 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5980 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5981 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5982 performance for very large process counts. 5983 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5984 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5985 functions, instead sending only neighbor messages. 5986 5987 Level: intermediate 5988 5989 Notes: 5990 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5991 5992 Some options are relevant only for particular matrix types and 5993 are thus ignored by others. Other options are not supported by 5994 certain matrix types and will generate an error message if set. 5995 5996 If using Fortran to compute a matrix, one may need to 5997 use the column-oriented option (or convert to the row-oriented 5998 format). 5999 6000 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6001 that would generate a new entry in the nonzero structure is instead 6002 ignored. Thus, if memory has not already been allocated for this particular 6003 data, then the insertion is ignored. For dense matrices, in which 6004 the entire array is allocated, no entries are ever ignored. 6005 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6006 6007 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6008 that would generate a new entry in the nonzero structure instead produces 6009 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 6010 6011 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6012 that would generate a new entry that has not been preallocated will 6013 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6014 only.) This is a useful flag when debugging matrix memory preallocation. 6015 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6016 6017 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6018 other processors should be dropped, rather than stashed. 6019 This is useful if you know that the "owning" processor is also 6020 always generating the correct matrix entries, so that PETSc need 6021 not transfer duplicate entries generated on another processor. 6022 6023 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6024 searches during matrix assembly. When this flag is set, the hash table 6025 is created during the first matrix assembly. This hash table is 6026 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6027 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6028 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6029 supported by `MATMPIBAIJ` format only. 6030 6031 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6032 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6033 6034 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6035 a zero location in the matrix 6036 6037 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6038 6039 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6040 zero row routines and thus improves performance for very large process counts. 6041 6042 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6043 part of the matrix (since they should match the upper triangular part). 6044 6045 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6046 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6047 with finite difference schemes with non-periodic boundary conditions. 6048 6049 Developer Note: 6050 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6051 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6052 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6053 not changed. 6054 6055 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6056 @*/ 6057 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6058 { 6059 PetscFunctionBegin; 6060 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6061 if (op > 0) { 6062 PetscValidLogicalCollectiveEnum(mat, op, 2); 6063 PetscValidLogicalCollectiveBool(mat, flg, 3); 6064 } 6065 6066 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); 6067 6068 switch (op) { 6069 case MAT_FORCE_DIAGONAL_ENTRIES: 6070 mat->force_diagonals = flg; 6071 PetscFunctionReturn(PETSC_SUCCESS); 6072 case MAT_NO_OFF_PROC_ENTRIES: 6073 mat->nooffprocentries = flg; 6074 PetscFunctionReturn(PETSC_SUCCESS); 6075 case MAT_SUBSET_OFF_PROC_ENTRIES: 6076 mat->assembly_subset = flg; 6077 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6078 #if !defined(PETSC_HAVE_MPIUNI) 6079 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6080 #endif 6081 mat->stash.first_assembly_done = PETSC_FALSE; 6082 } 6083 PetscFunctionReturn(PETSC_SUCCESS); 6084 case MAT_NO_OFF_PROC_ZERO_ROWS: 6085 mat->nooffproczerorows = flg; 6086 PetscFunctionReturn(PETSC_SUCCESS); 6087 case MAT_SPD: 6088 if (flg) { 6089 mat->spd = PETSC_BOOL3_TRUE; 6090 mat->symmetric = PETSC_BOOL3_TRUE; 6091 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6092 } else { 6093 mat->spd = PETSC_BOOL3_FALSE; 6094 } 6095 break; 6096 case MAT_SYMMETRIC: 6097 mat->symmetric = PetscBoolToBool3(flg); 6098 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6099 #if !defined(PETSC_USE_COMPLEX) 6100 mat->hermitian = PetscBoolToBool3(flg); 6101 #endif 6102 break; 6103 case MAT_HERMITIAN: 6104 mat->hermitian = PetscBoolToBool3(flg); 6105 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6106 #if !defined(PETSC_USE_COMPLEX) 6107 mat->symmetric = PetscBoolToBool3(flg); 6108 #endif 6109 break; 6110 case MAT_STRUCTURALLY_SYMMETRIC: 6111 mat->structurally_symmetric = PetscBoolToBool3(flg); 6112 break; 6113 case MAT_SYMMETRY_ETERNAL: 6114 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"); 6115 mat->symmetry_eternal = flg; 6116 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6117 break; 6118 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6119 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"); 6120 mat->structural_symmetry_eternal = flg; 6121 break; 6122 case MAT_SPD_ETERNAL: 6123 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"); 6124 mat->spd_eternal = flg; 6125 if (flg) { 6126 mat->structural_symmetry_eternal = PETSC_TRUE; 6127 mat->symmetry_eternal = PETSC_TRUE; 6128 } 6129 break; 6130 case MAT_STRUCTURE_ONLY: 6131 mat->structure_only = flg; 6132 break; 6133 case MAT_SORTED_FULL: 6134 mat->sortedfull = flg; 6135 break; 6136 default: 6137 break; 6138 } 6139 PetscTryTypeMethod(mat, setoption, op, flg); 6140 PetscFunctionReturn(PETSC_SUCCESS); 6141 } 6142 6143 /*@ 6144 MatGetOption - Gets a parameter option that has been set for a matrix. 6145 6146 Logically Collective 6147 6148 Input Parameters: 6149 + mat - the matrix 6150 - op - the option, this only responds to certain options, check the code for which ones 6151 6152 Output Parameter: 6153 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6154 6155 Level: intermediate 6156 6157 Notes: 6158 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6159 6160 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6161 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6162 6163 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6164 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6165 @*/ 6166 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6167 { 6168 PetscFunctionBegin; 6169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6170 PetscValidType(mat, 1); 6171 6172 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); 6173 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()"); 6174 6175 switch (op) { 6176 case MAT_NO_OFF_PROC_ENTRIES: 6177 *flg = mat->nooffprocentries; 6178 break; 6179 case MAT_NO_OFF_PROC_ZERO_ROWS: 6180 *flg = mat->nooffproczerorows; 6181 break; 6182 case MAT_SYMMETRIC: 6183 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6184 break; 6185 case MAT_HERMITIAN: 6186 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6187 break; 6188 case MAT_STRUCTURALLY_SYMMETRIC: 6189 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6190 break; 6191 case MAT_SPD: 6192 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6193 break; 6194 case MAT_SYMMETRY_ETERNAL: 6195 *flg = mat->symmetry_eternal; 6196 break; 6197 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6198 *flg = mat->symmetry_eternal; 6199 break; 6200 default: 6201 break; 6202 } 6203 PetscFunctionReturn(PETSC_SUCCESS); 6204 } 6205 6206 /*@ 6207 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6208 this routine retains the old nonzero structure. 6209 6210 Logically Collective 6211 6212 Input Parameter: 6213 . mat - the matrix 6214 6215 Level: intermediate 6216 6217 Note: 6218 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. 6219 See the Performance chapter of the users manual for information on preallocating matrices. 6220 6221 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6222 @*/ 6223 PetscErrorCode MatZeroEntries(Mat mat) 6224 { 6225 PetscFunctionBegin; 6226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6227 PetscValidType(mat, 1); 6228 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6229 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"); 6230 MatCheckPreallocated(mat, 1); 6231 6232 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6233 PetscUseTypeMethod(mat, zeroentries); 6234 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6235 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6236 PetscFunctionReturn(PETSC_SUCCESS); 6237 } 6238 6239 /*@ 6240 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6241 of a set of rows and columns of a matrix. 6242 6243 Collective 6244 6245 Input Parameters: 6246 + mat - the matrix 6247 . numRows - the number of rows/columns to zero 6248 . rows - the global row indices 6249 . diag - value put in the diagonal of the eliminated rows 6250 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6251 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6252 6253 Level: intermediate 6254 6255 Notes: 6256 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6257 6258 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6259 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 6260 6261 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6262 Krylov method to take advantage of the known solution on the zeroed rows. 6263 6264 For the parallel case, all processes that share the matrix (i.e., 6265 those in the communicator used for matrix creation) MUST call this 6266 routine, regardless of whether any rows being zeroed are owned by 6267 them. 6268 6269 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6270 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 6271 missing. 6272 6273 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6274 list only rows local to itself). 6275 6276 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6277 6278 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6279 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6280 @*/ 6281 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6282 { 6283 PetscFunctionBegin; 6284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6285 PetscValidType(mat, 1); 6286 if (numRows) PetscAssertPointer(rows, 3); 6287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6288 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6289 MatCheckPreallocated(mat, 1); 6290 6291 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6292 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6293 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6294 PetscFunctionReturn(PETSC_SUCCESS); 6295 } 6296 6297 /*@ 6298 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6299 of a set of rows and columns of a matrix. 6300 6301 Collective 6302 6303 Input Parameters: 6304 + mat - the matrix 6305 . is - the rows to zero 6306 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6307 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6308 - b - optional vector of right-hand side, that will be adjusted by provided solution 6309 6310 Level: intermediate 6311 6312 Note: 6313 See `MatZeroRowsColumns()` for details on how this routine operates. 6314 6315 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6316 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6317 @*/ 6318 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6319 { 6320 PetscInt numRows; 6321 const PetscInt *rows; 6322 6323 PetscFunctionBegin; 6324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6325 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6326 PetscValidType(mat, 1); 6327 PetscValidType(is, 2); 6328 PetscCall(ISGetLocalSize(is, &numRows)); 6329 PetscCall(ISGetIndices(is, &rows)); 6330 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6331 PetscCall(ISRestoreIndices(is, &rows)); 6332 PetscFunctionReturn(PETSC_SUCCESS); 6333 } 6334 6335 /*@ 6336 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6337 of a set of rows of a matrix. 6338 6339 Collective 6340 6341 Input Parameters: 6342 + mat - the matrix 6343 . numRows - the number of rows to zero 6344 . rows - the global row indices 6345 . diag - value put in the diagonal of the zeroed rows 6346 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6347 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6348 6349 Level: intermediate 6350 6351 Notes: 6352 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6353 6354 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6355 6356 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6357 Krylov method to take advantage of the known solution on the zeroed rows. 6358 6359 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) 6360 from the matrix. 6361 6362 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6363 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6364 formats this does not alter the nonzero structure. 6365 6366 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6367 of the matrix is not changed the values are 6368 merely zeroed. 6369 6370 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6371 formats can optionally remove the main diagonal entry from the 6372 nonzero structure as well, by passing 0.0 as the final argument). 6373 6374 For the parallel case, all processes that share the matrix (i.e., 6375 those in the communicator used for matrix creation) MUST call this 6376 routine, regardless of whether any rows being zeroed are owned by 6377 them. 6378 6379 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6380 list only rows local to itself). 6381 6382 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6383 owns that are to be zeroed. This saves a global synchronization in the implementation. 6384 6385 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6386 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6387 @*/ 6388 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6389 { 6390 PetscFunctionBegin; 6391 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6392 PetscValidType(mat, 1); 6393 if (numRows) PetscAssertPointer(rows, 3); 6394 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6395 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6396 MatCheckPreallocated(mat, 1); 6397 6398 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6399 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6400 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6401 PetscFunctionReturn(PETSC_SUCCESS); 6402 } 6403 6404 /*@ 6405 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6406 of a set of rows of a matrix indicated by an `IS` 6407 6408 Collective 6409 6410 Input Parameters: 6411 + mat - the matrix 6412 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6413 . diag - value put in all diagonals of eliminated rows 6414 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6415 - b - optional vector of right-hand side, that will be adjusted by provided solution 6416 6417 Level: intermediate 6418 6419 Note: 6420 See `MatZeroRows()` for details on how this routine operates. 6421 6422 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6423 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6424 @*/ 6425 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6426 { 6427 PetscInt numRows = 0; 6428 const PetscInt *rows = NULL; 6429 6430 PetscFunctionBegin; 6431 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6432 PetscValidType(mat, 1); 6433 if (is) { 6434 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6435 PetscCall(ISGetLocalSize(is, &numRows)); 6436 PetscCall(ISGetIndices(is, &rows)); 6437 } 6438 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6439 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6440 PetscFunctionReturn(PETSC_SUCCESS); 6441 } 6442 6443 /*@ 6444 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6445 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6446 6447 Collective 6448 6449 Input Parameters: 6450 + mat - the matrix 6451 . numRows - the number of rows to remove 6452 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6453 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6454 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6455 - b - optional vector of right-hand side, that will be adjusted by provided solution 6456 6457 Level: intermediate 6458 6459 Notes: 6460 See `MatZeroRows()` for details on how this routine operates. 6461 6462 The grid coordinates are across the entire grid, not just the local portion 6463 6464 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6465 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6466 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6467 `DM_BOUNDARY_PERIODIC` boundary type. 6468 6469 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 6470 a single value per point) you can skip filling those indices. 6471 6472 Fortran Note: 6473 `idxm` and `idxn` should be declared as 6474 .vb 6475 MatStencil idxm(4, m) 6476 .ve 6477 and the values inserted using 6478 .vb 6479 idxm(MatStencil_i, 1) = i 6480 idxm(MatStencil_j, 1) = j 6481 idxm(MatStencil_k, 1) = k 6482 idxm(MatStencil_c, 1) = c 6483 etc 6484 .ve 6485 6486 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6487 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6488 @*/ 6489 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6490 { 6491 PetscInt dim = mat->stencil.dim; 6492 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6493 PetscInt *dims = mat->stencil.dims + 1; 6494 PetscInt *starts = mat->stencil.starts; 6495 PetscInt *dxm = (PetscInt *)rows; 6496 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6497 6498 PetscFunctionBegin; 6499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6500 PetscValidType(mat, 1); 6501 if (numRows) PetscAssertPointer(rows, 3); 6502 6503 PetscCall(PetscMalloc1(numRows, &jdxm)); 6504 for (i = 0; i < numRows; ++i) { 6505 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6506 for (j = 0; j < 3 - sdim; ++j) dxm++; 6507 /* Local index in X dir */ 6508 tmp = *dxm++ - starts[0]; 6509 /* Loop over remaining dimensions */ 6510 for (j = 0; j < dim - 1; ++j) { 6511 /* If nonlocal, set index to be negative */ 6512 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6513 /* Update local index */ 6514 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6515 } 6516 /* Skip component slot if necessary */ 6517 if (mat->stencil.noc) dxm++; 6518 /* Local row number */ 6519 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6520 } 6521 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6522 PetscCall(PetscFree(jdxm)); 6523 PetscFunctionReturn(PETSC_SUCCESS); 6524 } 6525 6526 /*@ 6527 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6528 of a set of rows and columns of a matrix. 6529 6530 Collective 6531 6532 Input Parameters: 6533 + mat - the matrix 6534 . numRows - the number of rows/columns to remove 6535 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6536 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6537 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6538 - b - optional vector of right-hand side, that will be adjusted by provided solution 6539 6540 Level: intermediate 6541 6542 Notes: 6543 See `MatZeroRowsColumns()` for details on how this routine operates. 6544 6545 The grid coordinates are across the entire grid, not just the local portion 6546 6547 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6548 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6549 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6550 `DM_BOUNDARY_PERIODIC` boundary type. 6551 6552 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 6553 a single value per point) you can skip filling those indices. 6554 6555 Fortran Note: 6556 `idxm` and `idxn` should be declared as 6557 .vb 6558 MatStencil idxm(4, m) 6559 .ve 6560 and the values inserted using 6561 .vb 6562 idxm(MatStencil_i, 1) = i 6563 idxm(MatStencil_j, 1) = j 6564 idxm(MatStencil_k, 1) = k 6565 idxm(MatStencil_c, 1) = c 6566 etc 6567 .ve 6568 6569 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6570 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6571 @*/ 6572 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6573 { 6574 PetscInt dim = mat->stencil.dim; 6575 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6576 PetscInt *dims = mat->stencil.dims + 1; 6577 PetscInt *starts = mat->stencil.starts; 6578 PetscInt *dxm = (PetscInt *)rows; 6579 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6580 6581 PetscFunctionBegin; 6582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6583 PetscValidType(mat, 1); 6584 if (numRows) PetscAssertPointer(rows, 3); 6585 6586 PetscCall(PetscMalloc1(numRows, &jdxm)); 6587 for (i = 0; i < numRows; ++i) { 6588 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6589 for (j = 0; j < 3 - sdim; ++j) dxm++; 6590 /* Local index in X dir */ 6591 tmp = *dxm++ - starts[0]; 6592 /* Loop over remaining dimensions */ 6593 for (j = 0; j < dim - 1; ++j) { 6594 /* If nonlocal, set index to be negative */ 6595 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6596 /* Update local index */ 6597 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6598 } 6599 /* Skip component slot if necessary */ 6600 if (mat->stencil.noc) dxm++; 6601 /* Local row number */ 6602 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6603 } 6604 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6605 PetscCall(PetscFree(jdxm)); 6606 PetscFunctionReturn(PETSC_SUCCESS); 6607 } 6608 6609 /*@ 6610 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6611 of a set of rows of a matrix; using local numbering of rows. 6612 6613 Collective 6614 6615 Input Parameters: 6616 + mat - the matrix 6617 . numRows - the number of rows to remove 6618 . rows - the local row indices 6619 . diag - value put in all diagonals of eliminated rows 6620 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6621 - b - optional vector of right-hand side, that will be adjusted by provided solution 6622 6623 Level: intermediate 6624 6625 Notes: 6626 Before calling `MatZeroRowsLocal()`, the user must first set the 6627 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6628 6629 See `MatZeroRows()` for details on how this routine operates. 6630 6631 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6632 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6633 @*/ 6634 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6635 { 6636 PetscFunctionBegin; 6637 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6638 PetscValidType(mat, 1); 6639 if (numRows) PetscAssertPointer(rows, 3); 6640 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6641 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6642 MatCheckPreallocated(mat, 1); 6643 6644 if (mat->ops->zerorowslocal) { 6645 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6646 } else { 6647 IS is, newis; 6648 const PetscInt *newRows; 6649 6650 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6651 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6652 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6653 PetscCall(ISGetIndices(newis, &newRows)); 6654 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6655 PetscCall(ISRestoreIndices(newis, &newRows)); 6656 PetscCall(ISDestroy(&newis)); 6657 PetscCall(ISDestroy(&is)); 6658 } 6659 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6660 PetscFunctionReturn(PETSC_SUCCESS); 6661 } 6662 6663 /*@ 6664 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6665 of a set of rows of a matrix; using local numbering of rows. 6666 6667 Collective 6668 6669 Input Parameters: 6670 + mat - the matrix 6671 . is - index set of rows to remove 6672 . diag - value put in all diagonals of eliminated rows 6673 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6674 - b - optional vector of right-hand side, that will be adjusted by provided solution 6675 6676 Level: intermediate 6677 6678 Notes: 6679 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6680 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6681 6682 See `MatZeroRows()` for details on how this routine operates. 6683 6684 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6685 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6686 @*/ 6687 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6688 { 6689 PetscInt numRows; 6690 const PetscInt *rows; 6691 6692 PetscFunctionBegin; 6693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6694 PetscValidType(mat, 1); 6695 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6696 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6697 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6698 MatCheckPreallocated(mat, 1); 6699 6700 PetscCall(ISGetLocalSize(is, &numRows)); 6701 PetscCall(ISGetIndices(is, &rows)); 6702 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6703 PetscCall(ISRestoreIndices(is, &rows)); 6704 PetscFunctionReturn(PETSC_SUCCESS); 6705 } 6706 6707 /*@ 6708 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6709 of a set of rows and columns of a matrix; using local numbering of rows. 6710 6711 Collective 6712 6713 Input Parameters: 6714 + mat - the matrix 6715 . numRows - the number of rows to remove 6716 . rows - the global row indices 6717 . diag - value put in all diagonals of eliminated rows 6718 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6719 - b - optional vector of right-hand side, that will be adjusted by provided solution 6720 6721 Level: intermediate 6722 6723 Notes: 6724 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6725 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6726 6727 See `MatZeroRowsColumns()` for details on how this routine operates. 6728 6729 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6730 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6731 @*/ 6732 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6733 { 6734 IS is, newis; 6735 const PetscInt *newRows; 6736 6737 PetscFunctionBegin; 6738 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6739 PetscValidType(mat, 1); 6740 if (numRows) PetscAssertPointer(rows, 3); 6741 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6742 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6743 MatCheckPreallocated(mat, 1); 6744 6745 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6746 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6747 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6748 PetscCall(ISGetIndices(newis, &newRows)); 6749 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6750 PetscCall(ISRestoreIndices(newis, &newRows)); 6751 PetscCall(ISDestroy(&newis)); 6752 PetscCall(ISDestroy(&is)); 6753 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6754 PetscFunctionReturn(PETSC_SUCCESS); 6755 } 6756 6757 /*@ 6758 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6759 of a set of rows and columns of a matrix; using local numbering of rows. 6760 6761 Collective 6762 6763 Input Parameters: 6764 + mat - the matrix 6765 . is - index set of rows to remove 6766 . diag - value put in all diagonals of eliminated rows 6767 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6768 - b - optional vector of right-hand side, that will be adjusted by provided solution 6769 6770 Level: intermediate 6771 6772 Notes: 6773 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6774 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6775 6776 See `MatZeroRowsColumns()` for details on how this routine operates. 6777 6778 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6779 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6780 @*/ 6781 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6782 { 6783 PetscInt numRows; 6784 const PetscInt *rows; 6785 6786 PetscFunctionBegin; 6787 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6788 PetscValidType(mat, 1); 6789 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6790 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6791 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6792 MatCheckPreallocated(mat, 1); 6793 6794 PetscCall(ISGetLocalSize(is, &numRows)); 6795 PetscCall(ISGetIndices(is, &rows)); 6796 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6797 PetscCall(ISRestoreIndices(is, &rows)); 6798 PetscFunctionReturn(PETSC_SUCCESS); 6799 } 6800 6801 /*@ 6802 MatGetSize - Returns the numbers of rows and columns in a matrix. 6803 6804 Not Collective 6805 6806 Input Parameter: 6807 . mat - the matrix 6808 6809 Output Parameters: 6810 + m - the number of global rows 6811 - n - the number of global columns 6812 6813 Level: beginner 6814 6815 Note: 6816 Both output parameters can be `NULL` on input. 6817 6818 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6819 @*/ 6820 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6821 { 6822 PetscFunctionBegin; 6823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6824 if (m) *m = mat->rmap->N; 6825 if (n) *n = mat->cmap->N; 6826 PetscFunctionReturn(PETSC_SUCCESS); 6827 } 6828 6829 /*@ 6830 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6831 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6832 6833 Not Collective 6834 6835 Input Parameter: 6836 . mat - the matrix 6837 6838 Output Parameters: 6839 + m - the number of local rows, use `NULL` to not obtain this value 6840 - n - the number of local columns, use `NULL` to not obtain this value 6841 6842 Level: beginner 6843 6844 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6845 @*/ 6846 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6847 { 6848 PetscFunctionBegin; 6849 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6850 if (m) PetscAssertPointer(m, 2); 6851 if (n) PetscAssertPointer(n, 3); 6852 if (m) *m = mat->rmap->n; 6853 if (n) *n = mat->cmap->n; 6854 PetscFunctionReturn(PETSC_SUCCESS); 6855 } 6856 6857 /*@ 6858 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6859 vector one multiplies this matrix by that are owned by this processor. 6860 6861 Not Collective, unless matrix has not been allocated, then collective 6862 6863 Input Parameter: 6864 . mat - the matrix 6865 6866 Output Parameters: 6867 + m - the global index of the first local column, use `NULL` to not obtain this value 6868 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6869 6870 Level: developer 6871 6872 Notes: 6873 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6874 6875 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6876 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6877 6878 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6879 the local values in the matrix. 6880 6881 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6882 Layouts](sec_matlayout) for details on matrix layouts. 6883 6884 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6885 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6886 @*/ 6887 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6888 { 6889 PetscFunctionBegin; 6890 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6891 PetscValidType(mat, 1); 6892 if (m) PetscAssertPointer(m, 2); 6893 if (n) PetscAssertPointer(n, 3); 6894 MatCheckPreallocated(mat, 1); 6895 if (m) *m = mat->cmap->rstart; 6896 if (n) *n = mat->cmap->rend; 6897 PetscFunctionReturn(PETSC_SUCCESS); 6898 } 6899 6900 /*@ 6901 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6902 this MPI process. 6903 6904 Not Collective 6905 6906 Input Parameter: 6907 . mat - the matrix 6908 6909 Output Parameters: 6910 + m - the global index of the first local row, use `NULL` to not obtain this value 6911 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6912 6913 Level: beginner 6914 6915 Notes: 6916 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6917 6918 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6919 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6920 6921 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6922 the local values in the matrix. 6923 6924 The high argument is one more than the last element stored locally. 6925 6926 For all matrices it returns the range of matrix rows associated with rows of a vector that 6927 would contain the result of a matrix vector product with this matrix. See [Matrix 6928 Layouts](sec_matlayout) for details on matrix layouts. 6929 6930 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6931 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6932 @*/ 6933 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6934 { 6935 PetscFunctionBegin; 6936 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6937 PetscValidType(mat, 1); 6938 if (m) PetscAssertPointer(m, 2); 6939 if (n) PetscAssertPointer(n, 3); 6940 MatCheckPreallocated(mat, 1); 6941 if (m) *m = mat->rmap->rstart; 6942 if (n) *n = mat->rmap->rend; 6943 PetscFunctionReturn(PETSC_SUCCESS); 6944 } 6945 6946 /*@C 6947 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6948 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6949 6950 Not Collective, unless matrix has not been allocated 6951 6952 Input Parameter: 6953 . mat - the matrix 6954 6955 Output Parameter: 6956 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6957 where `size` is the number of MPI processes used by `mat` 6958 6959 Level: beginner 6960 6961 Notes: 6962 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6963 6964 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6965 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6966 6967 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6968 the local values in the matrix. 6969 6970 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6971 would contain the result of a matrix vector product with this matrix. See [Matrix 6972 Layouts](sec_matlayout) for details on matrix layouts. 6973 6974 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6975 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6976 `DMDAGetGhostCorners()`, `DM` 6977 @*/ 6978 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6979 { 6980 PetscFunctionBegin; 6981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6982 PetscValidType(mat, 1); 6983 MatCheckPreallocated(mat, 1); 6984 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6985 PetscFunctionReturn(PETSC_SUCCESS); 6986 } 6987 6988 /*@C 6989 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6990 vector one multiplies this vector by that are owned by each processor. 6991 6992 Not Collective, unless matrix has not been allocated 6993 6994 Input Parameter: 6995 . mat - the matrix 6996 6997 Output Parameter: 6998 . ranges - start of each processors portion plus one more than the total length at the end 6999 7000 Level: beginner 7001 7002 Notes: 7003 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7004 7005 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7006 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7007 7008 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7009 the local values in the matrix. 7010 7011 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7012 Layouts](sec_matlayout) for details on matrix layouts. 7013 7014 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7015 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7016 `DMDAGetGhostCorners()`, `DM` 7017 @*/ 7018 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7019 { 7020 PetscFunctionBegin; 7021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7022 PetscValidType(mat, 1); 7023 MatCheckPreallocated(mat, 1); 7024 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7025 PetscFunctionReturn(PETSC_SUCCESS); 7026 } 7027 7028 /*@ 7029 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7030 7031 Not Collective 7032 7033 Input Parameter: 7034 . A - matrix 7035 7036 Output Parameters: 7037 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7038 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7039 7040 Level: intermediate 7041 7042 Note: 7043 You should call `ISDestroy()` on the returned `IS` 7044 7045 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7046 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7047 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7048 details on matrix layouts. 7049 7050 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7051 @*/ 7052 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7053 { 7054 PetscErrorCode (*f)(Mat, IS *, IS *); 7055 7056 PetscFunctionBegin; 7057 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7058 PetscValidType(A, 1); 7059 MatCheckPreallocated(A, 1); 7060 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7061 if (f) { 7062 PetscCall((*f)(A, rows, cols)); 7063 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7064 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7065 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7066 } 7067 PetscFunctionReturn(PETSC_SUCCESS); 7068 } 7069 7070 /*@ 7071 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7072 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7073 to complete the factorization. 7074 7075 Collective 7076 7077 Input Parameters: 7078 + fact - the factorized matrix obtained with `MatGetFactor()` 7079 . mat - the matrix 7080 . row - row permutation 7081 . col - column permutation 7082 - info - structure containing 7083 .vb 7084 levels - number of levels of fill. 7085 expected fill - as ratio of original fill. 7086 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7087 missing diagonal entries) 7088 .ve 7089 7090 Level: developer 7091 7092 Notes: 7093 See [Matrix Factorization](sec_matfactor) for additional information. 7094 7095 Most users should employ the `KSP` interface for linear solvers 7096 instead of working directly with matrix algebra routines such as this. 7097 See, e.g., `KSPCreate()`. 7098 7099 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7100 7101 Developer Note: 7102 The Fortran interface is not autogenerated as the 7103 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7104 7105 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7106 `MatGetOrdering()`, `MatFactorInfo` 7107 @*/ 7108 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7109 { 7110 PetscFunctionBegin; 7111 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7112 PetscValidType(mat, 2); 7113 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7114 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7115 PetscAssertPointer(info, 5); 7116 PetscAssertPointer(fact, 1); 7117 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7118 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7119 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7120 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7121 MatCheckPreallocated(mat, 2); 7122 7123 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7124 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7125 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7126 PetscFunctionReturn(PETSC_SUCCESS); 7127 } 7128 7129 /*@ 7130 MatICCFactorSymbolic - Performs symbolic incomplete 7131 Cholesky factorization for a symmetric matrix. Use 7132 `MatCholeskyFactorNumeric()` to complete the factorization. 7133 7134 Collective 7135 7136 Input Parameters: 7137 + fact - the factorized matrix obtained with `MatGetFactor()` 7138 . mat - the matrix to be factored 7139 . perm - row and column permutation 7140 - info - structure containing 7141 .vb 7142 levels - number of levels of fill. 7143 expected fill - as ratio of original fill. 7144 .ve 7145 7146 Level: developer 7147 7148 Notes: 7149 Most users should employ the `KSP` interface for linear solvers 7150 instead of working directly with matrix algebra routines such as this. 7151 See, e.g., `KSPCreate()`. 7152 7153 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7154 7155 Developer Note: 7156 The Fortran interface is not autogenerated as the 7157 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7158 7159 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7160 @*/ 7161 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7162 { 7163 PetscFunctionBegin; 7164 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7165 PetscValidType(mat, 2); 7166 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7167 PetscAssertPointer(info, 4); 7168 PetscAssertPointer(fact, 1); 7169 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7170 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7171 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7172 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7173 MatCheckPreallocated(mat, 2); 7174 7175 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7176 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7177 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7178 PetscFunctionReturn(PETSC_SUCCESS); 7179 } 7180 7181 /*@C 7182 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7183 points to an array of valid matrices, they may be reused to store the new 7184 submatrices. 7185 7186 Collective 7187 7188 Input Parameters: 7189 + mat - the matrix 7190 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7191 . irow - index set of rows to extract 7192 . icol - index set of columns to extract 7193 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7194 7195 Output Parameter: 7196 . submat - the array of submatrices 7197 7198 Level: advanced 7199 7200 Notes: 7201 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7202 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7203 to extract a parallel submatrix. 7204 7205 Some matrix types place restrictions on the row and column 7206 indices, such as that they be sorted or that they be equal to each other. 7207 7208 The index sets may not have duplicate entries. 7209 7210 When extracting submatrices from a parallel matrix, each processor can 7211 form a different submatrix by setting the rows and columns of its 7212 individual index sets according to the local submatrix desired. 7213 7214 When finished using the submatrices, the user should destroy 7215 them with `MatDestroySubMatrices()`. 7216 7217 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7218 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7219 7220 This routine creates the matrices in submat; you should NOT create them before 7221 calling it. It also allocates the array of matrix pointers submat. 7222 7223 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7224 request one row/column in a block, they must request all rows/columns that are in 7225 that block. For example, if the block size is 2 you cannot request just row 0 and 7226 column 0. 7227 7228 Fortran Note: 7229 .vb 7230 Mat, pointer :: submat(:) 7231 .ve 7232 7233 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7234 @*/ 7235 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7236 { 7237 PetscInt i; 7238 PetscBool eq; 7239 7240 PetscFunctionBegin; 7241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7242 PetscValidType(mat, 1); 7243 if (n) { 7244 PetscAssertPointer(irow, 3); 7245 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7246 PetscAssertPointer(icol, 4); 7247 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7248 } 7249 PetscAssertPointer(submat, 6); 7250 if (n && scall == MAT_REUSE_MATRIX) { 7251 PetscAssertPointer(*submat, 6); 7252 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7253 } 7254 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7255 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7256 MatCheckPreallocated(mat, 1); 7257 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7258 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7259 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7260 for (i = 0; i < n; i++) { 7261 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7262 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7263 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7264 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7265 if (mat->boundtocpu && mat->bindingpropagates) { 7266 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7267 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7268 } 7269 #endif 7270 } 7271 PetscFunctionReturn(PETSC_SUCCESS); 7272 } 7273 7274 /*@C 7275 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7276 7277 Collective 7278 7279 Input Parameters: 7280 + mat - the matrix 7281 . n - the number of submatrixes to be extracted 7282 . irow - index set of rows to extract 7283 . icol - index set of columns to extract 7284 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7285 7286 Output Parameter: 7287 . submat - the array of submatrices 7288 7289 Level: advanced 7290 7291 Note: 7292 This is used by `PCGASM` 7293 7294 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7295 @*/ 7296 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7297 { 7298 PetscInt i; 7299 PetscBool eq; 7300 7301 PetscFunctionBegin; 7302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7303 PetscValidType(mat, 1); 7304 if (n) { 7305 PetscAssertPointer(irow, 3); 7306 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7307 PetscAssertPointer(icol, 4); 7308 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7309 } 7310 PetscAssertPointer(submat, 6); 7311 if (n && scall == MAT_REUSE_MATRIX) { 7312 PetscAssertPointer(*submat, 6); 7313 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7314 } 7315 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7316 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7317 MatCheckPreallocated(mat, 1); 7318 7319 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7320 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7321 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7322 for (i = 0; i < n; i++) { 7323 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7324 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7325 } 7326 PetscFunctionReturn(PETSC_SUCCESS); 7327 } 7328 7329 /*@C 7330 MatDestroyMatrices - Destroys an array of matrices 7331 7332 Collective 7333 7334 Input Parameters: 7335 + n - the number of local matrices 7336 - mat - the matrices (this is a pointer to the array of matrices) 7337 7338 Level: advanced 7339 7340 Notes: 7341 Frees not only the matrices, but also the array that contains the matrices 7342 7343 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7344 7345 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7346 @*/ 7347 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7348 { 7349 PetscInt i; 7350 7351 PetscFunctionBegin; 7352 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7353 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7354 PetscAssertPointer(mat, 2); 7355 7356 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7357 7358 /* memory is allocated even if n = 0 */ 7359 PetscCall(PetscFree(*mat)); 7360 PetscFunctionReturn(PETSC_SUCCESS); 7361 } 7362 7363 /*@C 7364 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7365 7366 Collective 7367 7368 Input Parameters: 7369 + n - the number of local matrices 7370 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7371 7372 Level: advanced 7373 7374 Note: 7375 Frees not only the matrices, but also the array that contains the matrices 7376 7377 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7378 @*/ 7379 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7380 { 7381 Mat mat0; 7382 7383 PetscFunctionBegin; 7384 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7385 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7386 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7387 PetscAssertPointer(mat, 2); 7388 7389 mat0 = (*mat)[0]; 7390 if (mat0 && mat0->ops->destroysubmatrices) { 7391 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7392 } else { 7393 PetscCall(MatDestroyMatrices(n, mat)); 7394 } 7395 PetscFunctionReturn(PETSC_SUCCESS); 7396 } 7397 7398 /*@ 7399 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7400 7401 Collective 7402 7403 Input Parameter: 7404 . mat - the matrix 7405 7406 Output Parameter: 7407 . matstruct - the sequential matrix with the nonzero structure of `mat` 7408 7409 Level: developer 7410 7411 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7412 @*/ 7413 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7414 { 7415 PetscFunctionBegin; 7416 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7417 PetscAssertPointer(matstruct, 2); 7418 7419 PetscValidType(mat, 1); 7420 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7421 MatCheckPreallocated(mat, 1); 7422 7423 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7424 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7425 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7426 PetscFunctionReturn(PETSC_SUCCESS); 7427 } 7428 7429 /*@C 7430 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7431 7432 Collective 7433 7434 Input Parameter: 7435 . mat - the matrix 7436 7437 Level: advanced 7438 7439 Note: 7440 This is not needed, one can just call `MatDestroy()` 7441 7442 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7443 @*/ 7444 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7445 { 7446 PetscFunctionBegin; 7447 PetscAssertPointer(mat, 1); 7448 PetscCall(MatDestroy(mat)); 7449 PetscFunctionReturn(PETSC_SUCCESS); 7450 } 7451 7452 /*@ 7453 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7454 replaces the index sets by larger ones that represent submatrices with 7455 additional overlap. 7456 7457 Collective 7458 7459 Input Parameters: 7460 + mat - the matrix 7461 . n - the number of index sets 7462 . is - the array of index sets (these index sets will changed during the call) 7463 - ov - the additional overlap requested 7464 7465 Options Database Key: 7466 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7467 7468 Level: developer 7469 7470 Note: 7471 The computed overlap preserves the matrix block sizes when the blocks are square. 7472 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7473 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7474 7475 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7476 @*/ 7477 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7478 { 7479 PetscInt i, bs, cbs; 7480 7481 PetscFunctionBegin; 7482 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7483 PetscValidType(mat, 1); 7484 PetscValidLogicalCollectiveInt(mat, n, 2); 7485 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7486 if (n) { 7487 PetscAssertPointer(is, 3); 7488 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7489 } 7490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7492 MatCheckPreallocated(mat, 1); 7493 7494 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7495 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7496 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7497 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7498 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7499 if (bs == cbs) { 7500 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7501 } 7502 PetscFunctionReturn(PETSC_SUCCESS); 7503 } 7504 7505 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7506 7507 /*@ 7508 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7509 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7510 additional overlap. 7511 7512 Collective 7513 7514 Input Parameters: 7515 + mat - the matrix 7516 . n - the number of index sets 7517 . is - the array of index sets (these index sets will changed during the call) 7518 - ov - the additional overlap requested 7519 7520 ` Options Database Key: 7521 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7522 7523 Level: developer 7524 7525 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7526 @*/ 7527 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7528 { 7529 PetscInt i; 7530 7531 PetscFunctionBegin; 7532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7533 PetscValidType(mat, 1); 7534 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7535 if (n) { 7536 PetscAssertPointer(is, 3); 7537 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7538 } 7539 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7540 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7541 MatCheckPreallocated(mat, 1); 7542 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7543 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7544 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7545 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7546 PetscFunctionReturn(PETSC_SUCCESS); 7547 } 7548 7549 /*@ 7550 MatGetBlockSize - Returns the matrix block size. 7551 7552 Not Collective 7553 7554 Input Parameter: 7555 . mat - the matrix 7556 7557 Output Parameter: 7558 . bs - block size 7559 7560 Level: intermediate 7561 7562 Notes: 7563 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7564 7565 If the block size has not been set yet this routine returns 1. 7566 7567 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7568 @*/ 7569 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7570 { 7571 PetscFunctionBegin; 7572 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7573 PetscAssertPointer(bs, 2); 7574 *bs = mat->rmap->bs; 7575 PetscFunctionReturn(PETSC_SUCCESS); 7576 } 7577 7578 /*@ 7579 MatGetBlockSizes - Returns the matrix block row and column sizes. 7580 7581 Not Collective 7582 7583 Input Parameter: 7584 . mat - the matrix 7585 7586 Output Parameters: 7587 + rbs - row block size 7588 - cbs - column block size 7589 7590 Level: intermediate 7591 7592 Notes: 7593 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7594 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7595 7596 If a block size has not been set yet this routine returns 1. 7597 7598 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7599 @*/ 7600 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7601 { 7602 PetscFunctionBegin; 7603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7604 if (rbs) PetscAssertPointer(rbs, 2); 7605 if (cbs) PetscAssertPointer(cbs, 3); 7606 if (rbs) *rbs = mat->rmap->bs; 7607 if (cbs) *cbs = mat->cmap->bs; 7608 PetscFunctionReturn(PETSC_SUCCESS); 7609 } 7610 7611 /*@ 7612 MatSetBlockSize - Sets the matrix block size. 7613 7614 Logically Collective 7615 7616 Input Parameters: 7617 + mat - the matrix 7618 - bs - block size 7619 7620 Level: intermediate 7621 7622 Notes: 7623 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7624 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7625 7626 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7627 is compatible with the matrix local sizes. 7628 7629 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7630 @*/ 7631 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7632 { 7633 PetscFunctionBegin; 7634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7635 PetscValidLogicalCollectiveInt(mat, bs, 2); 7636 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7637 PetscFunctionReturn(PETSC_SUCCESS); 7638 } 7639 7640 typedef struct { 7641 PetscInt n; 7642 IS *is; 7643 Mat *mat; 7644 PetscObjectState nonzerostate; 7645 Mat C; 7646 } EnvelopeData; 7647 7648 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7649 { 7650 EnvelopeData *edata = (EnvelopeData *)*ptr; 7651 7652 PetscFunctionBegin; 7653 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7654 PetscCall(PetscFree(edata->is)); 7655 PetscCall(PetscFree(edata)); 7656 PetscFunctionReturn(PETSC_SUCCESS); 7657 } 7658 7659 /*@ 7660 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7661 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7662 7663 Collective 7664 7665 Input Parameter: 7666 . mat - the matrix 7667 7668 Level: intermediate 7669 7670 Notes: 7671 There can be zeros within the blocks 7672 7673 The blocks can overlap between processes, including laying on more than two processes 7674 7675 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7676 @*/ 7677 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7678 { 7679 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7680 PetscInt *diag, *odiag, sc; 7681 VecScatter scatter; 7682 PetscScalar *seqv; 7683 const PetscScalar *parv; 7684 const PetscInt *ia, *ja; 7685 PetscBool set, flag, done; 7686 Mat AA = mat, A; 7687 MPI_Comm comm; 7688 PetscMPIInt rank, size, tag; 7689 MPI_Status status; 7690 PetscContainer container; 7691 EnvelopeData *edata; 7692 Vec seq, par; 7693 IS isglobal; 7694 7695 PetscFunctionBegin; 7696 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7697 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7698 if (!set || !flag) { 7699 /* TODO: only needs nonzero structure of transpose */ 7700 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7701 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7702 } 7703 PetscCall(MatAIJGetLocalMat(AA, &A)); 7704 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7705 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7706 7707 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7708 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7709 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7710 PetscCallMPI(MPI_Comm_size(comm, &size)); 7711 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7712 7713 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7714 7715 if (rank > 0) { 7716 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7717 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7718 } 7719 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7720 for (i = 0; i < n; i++) { 7721 env = PetscMax(env, ja[ia[i + 1] - 1]); 7722 II = rstart + i; 7723 if (env == II) { 7724 starts[lblocks] = tbs; 7725 sizes[lblocks++] = 1 + II - tbs; 7726 tbs = 1 + II; 7727 } 7728 } 7729 if (rank < size - 1) { 7730 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7731 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7732 } 7733 7734 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7735 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7736 PetscCall(MatDestroy(&A)); 7737 7738 PetscCall(PetscNew(&edata)); 7739 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7740 edata->n = lblocks; 7741 /* create IS needed for extracting blocks from the original matrix */ 7742 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7743 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7744 7745 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7746 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7747 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7748 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7749 PetscCall(MatSetType(edata->C, MATAIJ)); 7750 7751 /* Communicate the start and end of each row, from each block to the correct rank */ 7752 /* TODO: Use PetscSF instead of VecScatter */ 7753 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7754 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7755 PetscCall(VecGetArrayWrite(seq, &seqv)); 7756 for (PetscInt i = 0; i < lblocks; i++) { 7757 for (PetscInt j = 0; j < sizes[i]; j++) { 7758 seqv[cnt] = starts[i]; 7759 seqv[cnt + 1] = starts[i] + sizes[i]; 7760 cnt += 2; 7761 } 7762 } 7763 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7764 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7765 sc -= cnt; 7766 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7767 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7768 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7769 PetscCall(ISDestroy(&isglobal)); 7770 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7771 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7772 PetscCall(VecScatterDestroy(&scatter)); 7773 PetscCall(VecDestroy(&seq)); 7774 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7775 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7776 PetscCall(VecGetArrayRead(par, &parv)); 7777 cnt = 0; 7778 PetscCall(MatGetSize(mat, NULL, &n)); 7779 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7780 PetscInt start, end, d = 0, od = 0; 7781 7782 start = (PetscInt)PetscRealPart(parv[cnt]); 7783 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7784 cnt += 2; 7785 7786 if (start < cstart) { 7787 od += cstart - start + n - cend; 7788 d += cend - cstart; 7789 } else if (start < cend) { 7790 od += n - cend; 7791 d += cend - start; 7792 } else od += n - start; 7793 if (end <= cstart) { 7794 od -= cstart - end + n - cend; 7795 d -= cend - cstart; 7796 } else if (end < cend) { 7797 od -= n - cend; 7798 d -= cend - end; 7799 } else od -= n - end; 7800 7801 odiag[i] = od; 7802 diag[i] = d; 7803 } 7804 PetscCall(VecRestoreArrayRead(par, &parv)); 7805 PetscCall(VecDestroy(&par)); 7806 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7807 PetscCall(PetscFree2(diag, odiag)); 7808 PetscCall(PetscFree2(sizes, starts)); 7809 7810 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7811 PetscCall(PetscContainerSetPointer(container, edata)); 7812 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7813 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7814 PetscCall(PetscObjectDereference((PetscObject)container)); 7815 PetscFunctionReturn(PETSC_SUCCESS); 7816 } 7817 7818 /*@ 7819 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7820 7821 Collective 7822 7823 Input Parameters: 7824 + A - the matrix 7825 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7826 7827 Output Parameter: 7828 . C - matrix with inverted block diagonal of `A` 7829 7830 Level: advanced 7831 7832 Note: 7833 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7834 7835 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7836 @*/ 7837 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7838 { 7839 PetscContainer container; 7840 EnvelopeData *edata; 7841 PetscObjectState nonzerostate; 7842 7843 PetscFunctionBegin; 7844 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7845 if (!container) { 7846 PetscCall(MatComputeVariableBlockEnvelope(A)); 7847 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7848 } 7849 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7850 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7851 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7852 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7853 7854 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7855 *C = edata->C; 7856 7857 for (PetscInt i = 0; i < edata->n; i++) { 7858 Mat D; 7859 PetscScalar *dvalues; 7860 7861 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7862 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7863 PetscCall(MatSeqDenseInvert(D)); 7864 PetscCall(MatDenseGetArray(D, &dvalues)); 7865 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7866 PetscCall(MatDestroy(&D)); 7867 } 7868 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7869 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7870 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7871 PetscFunctionReturn(PETSC_SUCCESS); 7872 } 7873 7874 /*@ 7875 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7876 7877 Not Collective 7878 7879 Input Parameters: 7880 + mat - the matrix 7881 . nblocks - the number of blocks on this process, each block can only exist on a single process 7882 - bsizes - the block sizes 7883 7884 Level: intermediate 7885 7886 Notes: 7887 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7888 7889 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. 7890 7891 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7892 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7893 @*/ 7894 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7895 { 7896 PetscInt ncnt = 0, nlocal; 7897 7898 PetscFunctionBegin; 7899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7900 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7901 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); 7902 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7903 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); 7904 PetscCall(PetscFree(mat->bsizes)); 7905 mat->nblocks = nblocks; 7906 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7907 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7908 PetscFunctionReturn(PETSC_SUCCESS); 7909 } 7910 7911 /*@C 7912 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7913 7914 Not Collective; No Fortran Support 7915 7916 Input Parameter: 7917 . mat - the matrix 7918 7919 Output Parameters: 7920 + nblocks - the number of blocks on this process 7921 - bsizes - the block sizes 7922 7923 Level: intermediate 7924 7925 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7926 @*/ 7927 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7928 { 7929 PetscFunctionBegin; 7930 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7931 if (nblocks) *nblocks = mat->nblocks; 7932 if (bsizes) *bsizes = mat->bsizes; 7933 PetscFunctionReturn(PETSC_SUCCESS); 7934 } 7935 7936 /*@ 7937 MatSetBlockSizes - Sets the matrix block row and column sizes. 7938 7939 Logically Collective 7940 7941 Input Parameters: 7942 + mat - the matrix 7943 . rbs - row block size 7944 - cbs - column block size 7945 7946 Level: intermediate 7947 7948 Notes: 7949 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7950 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7951 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7952 7953 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7954 are compatible with the matrix local sizes. 7955 7956 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7957 7958 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7959 @*/ 7960 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7961 { 7962 PetscFunctionBegin; 7963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7964 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7965 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7966 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7967 if (mat->rmap->refcnt) { 7968 ISLocalToGlobalMapping l2g = NULL; 7969 PetscLayout nmap = NULL; 7970 7971 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7972 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7973 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7974 mat->rmap = nmap; 7975 mat->rmap->mapping = l2g; 7976 } 7977 if (mat->cmap->refcnt) { 7978 ISLocalToGlobalMapping l2g = NULL; 7979 PetscLayout nmap = NULL; 7980 7981 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7982 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7983 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7984 mat->cmap = nmap; 7985 mat->cmap->mapping = l2g; 7986 } 7987 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7988 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7989 PetscFunctionReturn(PETSC_SUCCESS); 7990 } 7991 7992 /*@ 7993 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7994 7995 Logically Collective 7996 7997 Input Parameters: 7998 + mat - the matrix 7999 . fromRow - matrix from which to copy row block size 8000 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8001 8002 Level: developer 8003 8004 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8005 @*/ 8006 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8007 { 8008 PetscFunctionBegin; 8009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8010 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8011 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8012 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8013 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8014 PetscFunctionReturn(PETSC_SUCCESS); 8015 } 8016 8017 /*@ 8018 MatResidual - Default routine to calculate the residual r = b - Ax 8019 8020 Collective 8021 8022 Input Parameters: 8023 + mat - the matrix 8024 . b - the right-hand-side 8025 - x - the approximate solution 8026 8027 Output Parameter: 8028 . r - location to store the residual 8029 8030 Level: developer 8031 8032 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8033 @*/ 8034 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8035 { 8036 PetscFunctionBegin; 8037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8038 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8039 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8040 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8041 PetscValidType(mat, 1); 8042 MatCheckPreallocated(mat, 1); 8043 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8044 if (!mat->ops->residual) { 8045 PetscCall(MatMult(mat, x, r)); 8046 PetscCall(VecAYPX(r, -1.0, b)); 8047 } else { 8048 PetscUseTypeMethod(mat, residual, b, x, r); 8049 } 8050 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8051 PetscFunctionReturn(PETSC_SUCCESS); 8052 } 8053 8054 /*@C 8055 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8056 8057 Collective 8058 8059 Input Parameters: 8060 + mat - the matrix 8061 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8062 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8063 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8064 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8065 always used. 8066 8067 Output Parameters: 8068 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8069 . 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 8070 . ja - the column indices, use `NULL` if not needed 8071 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8072 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8073 8074 Level: developer 8075 8076 Notes: 8077 You CANNOT change any of the ia[] or ja[] values. 8078 8079 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8080 8081 Fortran Notes: 8082 Use 8083 .vb 8084 PetscInt, pointer :: ia(:),ja(:) 8085 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8086 ! Access the ith and jth entries via ia(i) and ja(j) 8087 .ve 8088 8089 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8090 @*/ 8091 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8092 { 8093 PetscFunctionBegin; 8094 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8095 PetscValidType(mat, 1); 8096 if (n) PetscAssertPointer(n, 5); 8097 if (ia) PetscAssertPointer(ia, 6); 8098 if (ja) PetscAssertPointer(ja, 7); 8099 if (done) PetscAssertPointer(done, 8); 8100 MatCheckPreallocated(mat, 1); 8101 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8102 else { 8103 if (done) *done = PETSC_TRUE; 8104 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8105 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8106 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8107 } 8108 PetscFunctionReturn(PETSC_SUCCESS); 8109 } 8110 8111 /*@C 8112 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8113 8114 Collective 8115 8116 Input Parameters: 8117 + mat - the matrix 8118 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8119 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8120 symmetrized 8121 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8122 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8123 always used. 8124 . n - number of columns in the (possibly compressed) matrix 8125 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8126 - ja - the row indices 8127 8128 Output Parameter: 8129 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8130 8131 Level: developer 8132 8133 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8134 @*/ 8135 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8136 { 8137 PetscFunctionBegin; 8138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8139 PetscValidType(mat, 1); 8140 PetscAssertPointer(n, 5); 8141 if (ia) PetscAssertPointer(ia, 6); 8142 if (ja) PetscAssertPointer(ja, 7); 8143 PetscAssertPointer(done, 8); 8144 MatCheckPreallocated(mat, 1); 8145 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8146 else { 8147 *done = PETSC_TRUE; 8148 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8149 } 8150 PetscFunctionReturn(PETSC_SUCCESS); 8151 } 8152 8153 /*@C 8154 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8155 8156 Collective 8157 8158 Input Parameters: 8159 + mat - the matrix 8160 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8161 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8162 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8163 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8164 always used. 8165 . n - size of (possibly compressed) matrix 8166 . ia - the row pointers 8167 - ja - the column indices 8168 8169 Output Parameter: 8170 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8171 8172 Level: developer 8173 8174 Note: 8175 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8176 us of the array after it has been restored. If you pass `NULL`, it will 8177 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8178 8179 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8180 @*/ 8181 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8182 { 8183 PetscFunctionBegin; 8184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8185 PetscValidType(mat, 1); 8186 if (ia) PetscAssertPointer(ia, 6); 8187 if (ja) PetscAssertPointer(ja, 7); 8188 if (done) PetscAssertPointer(done, 8); 8189 MatCheckPreallocated(mat, 1); 8190 8191 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8192 else { 8193 if (done) *done = PETSC_TRUE; 8194 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8195 if (n) *n = 0; 8196 if (ia) *ia = NULL; 8197 if (ja) *ja = NULL; 8198 } 8199 PetscFunctionReturn(PETSC_SUCCESS); 8200 } 8201 8202 /*@C 8203 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8204 8205 Collective 8206 8207 Input Parameters: 8208 + mat - the matrix 8209 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8210 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8211 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8212 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8213 always used. 8214 8215 Output Parameters: 8216 + n - size of (possibly compressed) matrix 8217 . ia - the column pointers 8218 . ja - the row indices 8219 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8220 8221 Level: developer 8222 8223 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8224 @*/ 8225 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8226 { 8227 PetscFunctionBegin; 8228 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8229 PetscValidType(mat, 1); 8230 if (ia) PetscAssertPointer(ia, 6); 8231 if (ja) PetscAssertPointer(ja, 7); 8232 PetscAssertPointer(done, 8); 8233 MatCheckPreallocated(mat, 1); 8234 8235 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8236 else { 8237 *done = PETSC_TRUE; 8238 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8239 if (n) *n = 0; 8240 if (ia) *ia = NULL; 8241 if (ja) *ja = NULL; 8242 } 8243 PetscFunctionReturn(PETSC_SUCCESS); 8244 } 8245 8246 /*@ 8247 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8248 `MatGetColumnIJ()`. 8249 8250 Collective 8251 8252 Input Parameters: 8253 + mat - the matrix 8254 . ncolors - maximum color value 8255 . n - number of entries in colorarray 8256 - colorarray - array indicating color for each column 8257 8258 Output Parameter: 8259 . iscoloring - coloring generated using colorarray information 8260 8261 Level: developer 8262 8263 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8264 @*/ 8265 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8266 { 8267 PetscFunctionBegin; 8268 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8269 PetscValidType(mat, 1); 8270 PetscAssertPointer(colorarray, 4); 8271 PetscAssertPointer(iscoloring, 5); 8272 MatCheckPreallocated(mat, 1); 8273 8274 if (!mat->ops->coloringpatch) { 8275 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8276 } else { 8277 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8278 } 8279 PetscFunctionReturn(PETSC_SUCCESS); 8280 } 8281 8282 /*@ 8283 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8284 8285 Logically Collective 8286 8287 Input Parameter: 8288 . mat - the factored matrix to be reset 8289 8290 Level: developer 8291 8292 Notes: 8293 This routine should be used only with factored matrices formed by in-place 8294 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8295 format). This option can save memory, for example, when solving nonlinear 8296 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8297 ILU(0) preconditioner. 8298 8299 One can specify in-place ILU(0) factorization by calling 8300 .vb 8301 PCType(pc,PCILU); 8302 PCFactorSeUseInPlace(pc); 8303 .ve 8304 or by using the options -pc_type ilu -pc_factor_in_place 8305 8306 In-place factorization ILU(0) can also be used as a local 8307 solver for the blocks within the block Jacobi or additive Schwarz 8308 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8309 for details on setting local solver options. 8310 8311 Most users should employ the `KSP` interface for linear solvers 8312 instead of working directly with matrix algebra routines such as this. 8313 See, e.g., `KSPCreate()`. 8314 8315 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8316 @*/ 8317 PetscErrorCode MatSetUnfactored(Mat mat) 8318 { 8319 PetscFunctionBegin; 8320 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8321 PetscValidType(mat, 1); 8322 MatCheckPreallocated(mat, 1); 8323 mat->factortype = MAT_FACTOR_NONE; 8324 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8325 PetscUseTypeMethod(mat, setunfactored); 8326 PetscFunctionReturn(PETSC_SUCCESS); 8327 } 8328 8329 /*@ 8330 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8331 as the original matrix. 8332 8333 Collective 8334 8335 Input Parameters: 8336 + mat - the original matrix 8337 . isrow - parallel `IS` containing the rows this processor should obtain 8338 . 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. 8339 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8340 8341 Output Parameter: 8342 . newmat - the new submatrix, of the same type as the original matrix 8343 8344 Level: advanced 8345 8346 Notes: 8347 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8348 8349 Some matrix types place restrictions on the row and column indices, such 8350 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; 8351 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8352 8353 The index sets may not have duplicate entries. 8354 8355 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8356 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8357 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8358 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8359 you are finished using it. 8360 8361 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8362 the input matrix. 8363 8364 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8365 8366 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8367 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8368 8369 Example usage: 8370 Consider the following 8x8 matrix with 34 non-zero values, that is 8371 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8372 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8373 as follows 8374 .vb 8375 1 2 0 | 0 3 0 | 0 4 8376 Proc0 0 5 6 | 7 0 0 | 8 0 8377 9 0 10 | 11 0 0 | 12 0 8378 ------------------------------------- 8379 13 0 14 | 15 16 17 | 0 0 8380 Proc1 0 18 0 | 19 20 21 | 0 0 8381 0 0 0 | 22 23 0 | 24 0 8382 ------------------------------------- 8383 Proc2 25 26 27 | 0 0 28 | 29 0 8384 30 0 0 | 31 32 33 | 0 34 8385 .ve 8386 8387 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8388 8389 .vb 8390 2 0 | 0 3 0 | 0 8391 Proc0 5 6 | 7 0 0 | 8 8392 ------------------------------- 8393 Proc1 18 0 | 19 20 21 | 0 8394 ------------------------------- 8395 Proc2 26 27 | 0 0 28 | 29 8396 0 0 | 31 32 33 | 0 8397 .ve 8398 8399 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8400 @*/ 8401 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8402 { 8403 PetscMPIInt size; 8404 Mat *local; 8405 IS iscoltmp; 8406 PetscBool flg; 8407 8408 PetscFunctionBegin; 8409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8410 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8411 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8412 PetscAssertPointer(newmat, 5); 8413 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8414 PetscValidType(mat, 1); 8415 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8416 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8417 8418 MatCheckPreallocated(mat, 1); 8419 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8420 8421 if (!iscol || isrow == iscol) { 8422 PetscBool stride; 8423 PetscMPIInt grabentirematrix = 0, grab; 8424 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8425 if (stride) { 8426 PetscInt first, step, n, rstart, rend; 8427 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8428 if (step == 1) { 8429 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8430 if (rstart == first) { 8431 PetscCall(ISGetLocalSize(isrow, &n)); 8432 if (n == rend - rstart) grabentirematrix = 1; 8433 } 8434 } 8435 } 8436 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8437 if (grab) { 8438 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8439 if (cll == MAT_INITIAL_MATRIX) { 8440 *newmat = mat; 8441 PetscCall(PetscObjectReference((PetscObject)mat)); 8442 } 8443 PetscFunctionReturn(PETSC_SUCCESS); 8444 } 8445 } 8446 8447 if (!iscol) { 8448 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8449 } else { 8450 iscoltmp = iscol; 8451 } 8452 8453 /* if original matrix is on just one processor then use submatrix generated */ 8454 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8455 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8456 goto setproperties; 8457 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8458 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8459 *newmat = *local; 8460 PetscCall(PetscFree(local)); 8461 goto setproperties; 8462 } else if (!mat->ops->createsubmatrix) { 8463 /* Create a new matrix type that implements the operation using the full matrix */ 8464 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8465 switch (cll) { 8466 case MAT_INITIAL_MATRIX: 8467 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8468 break; 8469 case MAT_REUSE_MATRIX: 8470 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8471 break; 8472 default: 8473 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8474 } 8475 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8476 goto setproperties; 8477 } 8478 8479 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8480 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8481 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8482 8483 setproperties: 8484 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8485 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8486 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8487 } 8488 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8489 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8490 PetscFunctionReturn(PETSC_SUCCESS); 8491 } 8492 8493 /*@ 8494 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8495 8496 Not Collective 8497 8498 Input Parameters: 8499 + A - the matrix we wish to propagate options from 8500 - B - the matrix we wish to propagate options to 8501 8502 Level: beginner 8503 8504 Note: 8505 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8506 8507 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8508 @*/ 8509 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8510 { 8511 PetscFunctionBegin; 8512 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8513 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8514 B->symmetry_eternal = A->symmetry_eternal; 8515 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8516 B->symmetric = A->symmetric; 8517 B->structurally_symmetric = A->structurally_symmetric; 8518 B->spd = A->spd; 8519 B->hermitian = A->hermitian; 8520 PetscFunctionReturn(PETSC_SUCCESS); 8521 } 8522 8523 /*@ 8524 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8525 used during the assembly process to store values that belong to 8526 other processors. 8527 8528 Not Collective 8529 8530 Input Parameters: 8531 + mat - the matrix 8532 . size - the initial size of the stash. 8533 - bsize - the initial size of the block-stash(if used). 8534 8535 Options Database Keys: 8536 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8537 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8538 8539 Level: intermediate 8540 8541 Notes: 8542 The block-stash is used for values set with `MatSetValuesBlocked()` while 8543 the stash is used for values set with `MatSetValues()` 8544 8545 Run with the option -info and look for output of the form 8546 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8547 to determine the appropriate value, MM, to use for size and 8548 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8549 to determine the value, BMM to use for bsize 8550 8551 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8552 @*/ 8553 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8554 { 8555 PetscFunctionBegin; 8556 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8557 PetscValidType(mat, 1); 8558 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8559 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8560 PetscFunctionReturn(PETSC_SUCCESS); 8561 } 8562 8563 /*@ 8564 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8565 the matrix 8566 8567 Neighbor-wise Collective 8568 8569 Input Parameters: 8570 + A - the matrix 8571 . x - the vector to be multiplied by the interpolation operator 8572 - y - the vector to be added to the result 8573 8574 Output Parameter: 8575 . w - the resulting vector 8576 8577 Level: intermediate 8578 8579 Notes: 8580 `w` may be the same vector as `y`. 8581 8582 This allows one to use either the restriction or interpolation (its transpose) 8583 matrix to do the interpolation 8584 8585 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8586 @*/ 8587 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8588 { 8589 PetscInt M, N, Ny; 8590 8591 PetscFunctionBegin; 8592 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8593 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8594 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8595 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8596 PetscCall(MatGetSize(A, &M, &N)); 8597 PetscCall(VecGetSize(y, &Ny)); 8598 if (M == Ny) { 8599 PetscCall(MatMultAdd(A, x, y, w)); 8600 } else { 8601 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8602 } 8603 PetscFunctionReturn(PETSC_SUCCESS); 8604 } 8605 8606 /*@ 8607 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8608 the matrix 8609 8610 Neighbor-wise Collective 8611 8612 Input Parameters: 8613 + A - the matrix 8614 - x - the vector to be interpolated 8615 8616 Output Parameter: 8617 . y - the resulting vector 8618 8619 Level: intermediate 8620 8621 Note: 8622 This allows one to use either the restriction or interpolation (its transpose) 8623 matrix to do the interpolation 8624 8625 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8626 @*/ 8627 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8628 { 8629 PetscInt M, N, Ny; 8630 8631 PetscFunctionBegin; 8632 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8633 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8634 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8635 PetscCall(MatGetSize(A, &M, &N)); 8636 PetscCall(VecGetSize(y, &Ny)); 8637 if (M == Ny) { 8638 PetscCall(MatMult(A, x, y)); 8639 } else { 8640 PetscCall(MatMultTranspose(A, x, y)); 8641 } 8642 PetscFunctionReturn(PETSC_SUCCESS); 8643 } 8644 8645 /*@ 8646 MatRestrict - $y = A*x$ or $A^T*x$ 8647 8648 Neighbor-wise Collective 8649 8650 Input Parameters: 8651 + A - the matrix 8652 - x - the vector to be restricted 8653 8654 Output Parameter: 8655 . y - the resulting vector 8656 8657 Level: intermediate 8658 8659 Note: 8660 This allows one to use either the restriction or interpolation (its transpose) 8661 matrix to do the restriction 8662 8663 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8664 @*/ 8665 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8666 { 8667 PetscInt M, N, Nx; 8668 8669 PetscFunctionBegin; 8670 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8671 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8672 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8673 PetscCall(MatGetSize(A, &M, &N)); 8674 PetscCall(VecGetSize(x, &Nx)); 8675 if (M == Nx) { 8676 PetscCall(MatMultTranspose(A, x, y)); 8677 } else { 8678 PetscCall(MatMult(A, x, y)); 8679 } 8680 PetscFunctionReturn(PETSC_SUCCESS); 8681 } 8682 8683 /*@ 8684 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8685 8686 Neighbor-wise Collective 8687 8688 Input Parameters: 8689 + A - the matrix 8690 . x - the input dense matrix to be multiplied 8691 - w - the input dense matrix to be added to the result 8692 8693 Output Parameter: 8694 . y - the output dense matrix 8695 8696 Level: intermediate 8697 8698 Note: 8699 This allows one to use either the restriction or interpolation (its transpose) 8700 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8701 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8702 8703 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8704 @*/ 8705 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8706 { 8707 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8708 PetscBool trans = PETSC_TRUE; 8709 MatReuse reuse = MAT_INITIAL_MATRIX; 8710 8711 PetscFunctionBegin; 8712 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8713 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8714 PetscValidType(x, 2); 8715 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8716 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8717 PetscCall(MatGetSize(A, &M, &N)); 8718 PetscCall(MatGetSize(x, &Mx, &Nx)); 8719 if (N == Mx) trans = PETSC_FALSE; 8720 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); 8721 Mo = trans ? N : M; 8722 if (*y) { 8723 PetscCall(MatGetSize(*y, &My, &Ny)); 8724 if (Mo == My && Nx == Ny) { 8725 reuse = MAT_REUSE_MATRIX; 8726 } else { 8727 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); 8728 PetscCall(MatDestroy(y)); 8729 } 8730 } 8731 8732 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8733 PetscBool flg; 8734 8735 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8736 if (w) { 8737 PetscInt My, Ny, Mw, Nw; 8738 8739 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8740 PetscCall(MatGetSize(*y, &My, &Ny)); 8741 PetscCall(MatGetSize(w, &Mw, &Nw)); 8742 if (!flg || My != Mw || Ny != Nw) w = NULL; 8743 } 8744 if (!w) { 8745 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8746 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8747 PetscCall(PetscObjectDereference((PetscObject)w)); 8748 } else { 8749 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8750 } 8751 } 8752 if (!trans) { 8753 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8754 } else { 8755 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8756 } 8757 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8758 PetscFunctionReturn(PETSC_SUCCESS); 8759 } 8760 8761 /*@ 8762 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8763 8764 Neighbor-wise Collective 8765 8766 Input Parameters: 8767 + A - the matrix 8768 - x - the input dense matrix 8769 8770 Output Parameter: 8771 . y - the output dense matrix 8772 8773 Level: intermediate 8774 8775 Note: 8776 This allows one to use either the restriction or interpolation (its transpose) 8777 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8778 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8779 8780 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8781 @*/ 8782 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8783 { 8784 PetscFunctionBegin; 8785 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8786 PetscFunctionReturn(PETSC_SUCCESS); 8787 } 8788 8789 /*@ 8790 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8791 8792 Neighbor-wise Collective 8793 8794 Input Parameters: 8795 + A - the matrix 8796 - x - the input dense matrix 8797 8798 Output Parameter: 8799 . y - the output dense matrix 8800 8801 Level: intermediate 8802 8803 Note: 8804 This allows one to use either the restriction or interpolation (its transpose) 8805 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8806 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8807 8808 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8809 @*/ 8810 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8811 { 8812 PetscFunctionBegin; 8813 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8814 PetscFunctionReturn(PETSC_SUCCESS); 8815 } 8816 8817 /*@ 8818 MatGetNullSpace - retrieves the null space of a matrix. 8819 8820 Logically Collective 8821 8822 Input Parameters: 8823 + mat - the matrix 8824 - nullsp - the null space object 8825 8826 Level: developer 8827 8828 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8829 @*/ 8830 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8831 { 8832 PetscFunctionBegin; 8833 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8834 PetscAssertPointer(nullsp, 2); 8835 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8836 PetscFunctionReturn(PETSC_SUCCESS); 8837 } 8838 8839 /*@C 8840 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8841 8842 Logically Collective 8843 8844 Input Parameters: 8845 + n - the number of matrices 8846 - mat - the array of matrices 8847 8848 Output Parameters: 8849 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8850 8851 Level: developer 8852 8853 Note: 8854 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8855 8856 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8857 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8858 @*/ 8859 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8860 { 8861 PetscFunctionBegin; 8862 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8863 PetscAssertPointer(mat, 2); 8864 PetscAssertPointer(nullsp, 3); 8865 8866 PetscCall(PetscCalloc1(3 * n, nullsp)); 8867 for (PetscInt i = 0; i < n; i++) { 8868 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8869 (*nullsp)[i] = mat[i]->nullsp; 8870 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8871 (*nullsp)[n + i] = mat[i]->nearnullsp; 8872 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8873 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8874 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8875 } 8876 PetscFunctionReturn(PETSC_SUCCESS); 8877 } 8878 8879 /*@C 8880 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8881 8882 Logically Collective 8883 8884 Input Parameters: 8885 + n - the number of matrices 8886 . mat - the array of matrices 8887 - nullsp - an array of null spaces 8888 8889 Level: developer 8890 8891 Note: 8892 Call `MatGetNullSpaces()` to create `nullsp` 8893 8894 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8895 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8896 @*/ 8897 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8898 { 8899 PetscFunctionBegin; 8900 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8901 PetscAssertPointer(mat, 2); 8902 PetscAssertPointer(nullsp, 3); 8903 PetscAssertPointer(*nullsp, 3); 8904 8905 for (PetscInt i = 0; i < n; i++) { 8906 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8907 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8908 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8909 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8910 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8911 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8912 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8913 } 8914 PetscCall(PetscFree(*nullsp)); 8915 PetscFunctionReturn(PETSC_SUCCESS); 8916 } 8917 8918 /*@ 8919 MatSetNullSpace - attaches a null space to a matrix. 8920 8921 Logically Collective 8922 8923 Input Parameters: 8924 + mat - the matrix 8925 - nullsp - the null space object 8926 8927 Level: advanced 8928 8929 Notes: 8930 This null space is used by the `KSP` linear solvers to solve singular systems. 8931 8932 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` 8933 8934 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 8935 to zero but the linear system will still be solved in a least squares sense. 8936 8937 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8938 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)$. 8939 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 8940 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 8941 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$). 8942 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8943 8944 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8945 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8946 routine also automatically calls `MatSetTransposeNullSpace()`. 8947 8948 The user should call `MatNullSpaceDestroy()`. 8949 8950 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8951 `KSPSetPCSide()` 8952 @*/ 8953 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8954 { 8955 PetscFunctionBegin; 8956 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8957 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8958 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8959 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8960 mat->nullsp = nullsp; 8961 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8962 PetscFunctionReturn(PETSC_SUCCESS); 8963 } 8964 8965 /*@ 8966 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8967 8968 Logically Collective 8969 8970 Input Parameters: 8971 + mat - the matrix 8972 - nullsp - the null space object 8973 8974 Level: developer 8975 8976 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8977 @*/ 8978 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8979 { 8980 PetscFunctionBegin; 8981 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8982 PetscValidType(mat, 1); 8983 PetscAssertPointer(nullsp, 2); 8984 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8985 PetscFunctionReturn(PETSC_SUCCESS); 8986 } 8987 8988 /*@ 8989 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8990 8991 Logically Collective 8992 8993 Input Parameters: 8994 + mat - the matrix 8995 - nullsp - the null space object 8996 8997 Level: advanced 8998 8999 Notes: 9000 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9001 9002 See `MatSetNullSpace()` 9003 9004 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9005 @*/ 9006 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9007 { 9008 PetscFunctionBegin; 9009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9010 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9011 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9012 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9013 mat->transnullsp = nullsp; 9014 PetscFunctionReturn(PETSC_SUCCESS); 9015 } 9016 9017 /*@ 9018 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9019 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9020 9021 Logically Collective 9022 9023 Input Parameters: 9024 + mat - the matrix 9025 - nullsp - the null space object 9026 9027 Level: advanced 9028 9029 Notes: 9030 Overwrites any previous near null space that may have been attached 9031 9032 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9033 9034 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9035 @*/ 9036 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9037 { 9038 PetscFunctionBegin; 9039 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9040 PetscValidType(mat, 1); 9041 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9042 MatCheckPreallocated(mat, 1); 9043 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9044 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9045 mat->nearnullsp = nullsp; 9046 PetscFunctionReturn(PETSC_SUCCESS); 9047 } 9048 9049 /*@ 9050 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9051 9052 Not Collective 9053 9054 Input Parameter: 9055 . mat - the matrix 9056 9057 Output Parameter: 9058 . nullsp - the null space object, `NULL` if not set 9059 9060 Level: advanced 9061 9062 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9063 @*/ 9064 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9065 { 9066 PetscFunctionBegin; 9067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9068 PetscValidType(mat, 1); 9069 PetscAssertPointer(nullsp, 2); 9070 MatCheckPreallocated(mat, 1); 9071 *nullsp = mat->nearnullsp; 9072 PetscFunctionReturn(PETSC_SUCCESS); 9073 } 9074 9075 /*@ 9076 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9077 9078 Collective 9079 9080 Input Parameters: 9081 + mat - the matrix 9082 . row - row/column permutation 9083 - info - information on desired factorization process 9084 9085 Level: developer 9086 9087 Notes: 9088 Probably really in-place only when level of fill is zero, otherwise allocates 9089 new space to store factored matrix and deletes previous memory. 9090 9091 Most users should employ the `KSP` interface for linear solvers 9092 instead of working directly with matrix algebra routines such as this. 9093 See, e.g., `KSPCreate()`. 9094 9095 Developer Note: 9096 The Fortran interface is not autogenerated as the 9097 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9098 9099 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9100 @*/ 9101 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9102 { 9103 PetscFunctionBegin; 9104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9105 PetscValidType(mat, 1); 9106 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9107 PetscAssertPointer(info, 3); 9108 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9109 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9110 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9111 MatCheckPreallocated(mat, 1); 9112 PetscUseTypeMethod(mat, iccfactor, row, info); 9113 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9114 PetscFunctionReturn(PETSC_SUCCESS); 9115 } 9116 9117 /*@ 9118 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9119 ghosted ones. 9120 9121 Not Collective 9122 9123 Input Parameters: 9124 + mat - the matrix 9125 - diag - the diagonal values, including ghost ones 9126 9127 Level: developer 9128 9129 Notes: 9130 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9131 9132 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9133 9134 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9135 @*/ 9136 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9137 { 9138 PetscMPIInt size; 9139 9140 PetscFunctionBegin; 9141 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9142 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9143 PetscValidType(mat, 1); 9144 9145 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9146 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9147 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9148 if (size == 1) { 9149 PetscInt n, m; 9150 PetscCall(VecGetSize(diag, &n)); 9151 PetscCall(MatGetSize(mat, NULL, &m)); 9152 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9153 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9154 } else { 9155 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9156 } 9157 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9158 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9159 PetscFunctionReturn(PETSC_SUCCESS); 9160 } 9161 9162 /*@ 9163 MatGetInertia - Gets the inertia from a factored matrix 9164 9165 Collective 9166 9167 Input Parameter: 9168 . mat - the matrix 9169 9170 Output Parameters: 9171 + nneg - number of negative eigenvalues 9172 . nzero - number of zero eigenvalues 9173 - npos - number of positive eigenvalues 9174 9175 Level: advanced 9176 9177 Note: 9178 Matrix must have been factored by `MatCholeskyFactor()` 9179 9180 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9181 @*/ 9182 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9183 { 9184 PetscFunctionBegin; 9185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9186 PetscValidType(mat, 1); 9187 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9188 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9189 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9190 PetscFunctionReturn(PETSC_SUCCESS); 9191 } 9192 9193 /*@C 9194 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9195 9196 Neighbor-wise Collective 9197 9198 Input Parameters: 9199 + mat - the factored matrix obtained with `MatGetFactor()` 9200 - b - the right-hand-side vectors 9201 9202 Output Parameter: 9203 . x - the result vectors 9204 9205 Level: developer 9206 9207 Note: 9208 The vectors `b` and `x` cannot be the same. I.e., one cannot 9209 call `MatSolves`(A,x,x). 9210 9211 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9212 @*/ 9213 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9214 { 9215 PetscFunctionBegin; 9216 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9217 PetscValidType(mat, 1); 9218 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9219 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9220 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9221 9222 MatCheckPreallocated(mat, 1); 9223 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9224 PetscUseTypeMethod(mat, solves, b, x); 9225 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9226 PetscFunctionReturn(PETSC_SUCCESS); 9227 } 9228 9229 /*@ 9230 MatIsSymmetric - Test whether a matrix is symmetric 9231 9232 Collective 9233 9234 Input Parameters: 9235 + A - the matrix to test 9236 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9237 9238 Output Parameter: 9239 . flg - the result 9240 9241 Level: intermediate 9242 9243 Notes: 9244 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9245 9246 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9247 9248 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9249 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9250 9251 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9252 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9253 @*/ 9254 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9255 { 9256 PetscFunctionBegin; 9257 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9258 PetscAssertPointer(flg, 3); 9259 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9260 else { 9261 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9262 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9263 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9264 } 9265 PetscFunctionReturn(PETSC_SUCCESS); 9266 } 9267 9268 /*@ 9269 MatIsHermitian - Test whether a matrix is Hermitian 9270 9271 Collective 9272 9273 Input Parameters: 9274 + A - the matrix to test 9275 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9276 9277 Output Parameter: 9278 . flg - the result 9279 9280 Level: intermediate 9281 9282 Notes: 9283 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9284 9285 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9286 9287 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9288 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9289 9290 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9291 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9292 @*/ 9293 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9294 { 9295 PetscFunctionBegin; 9296 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9297 PetscAssertPointer(flg, 3); 9298 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9299 else { 9300 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9301 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9302 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9303 } 9304 PetscFunctionReturn(PETSC_SUCCESS); 9305 } 9306 9307 /*@ 9308 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9309 9310 Not Collective 9311 9312 Input Parameter: 9313 . A - the matrix to check 9314 9315 Output Parameters: 9316 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9317 - flg - the result (only valid if set is `PETSC_TRUE`) 9318 9319 Level: advanced 9320 9321 Notes: 9322 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9323 if you want it explicitly checked 9324 9325 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9326 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9327 9328 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9329 @*/ 9330 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9331 { 9332 PetscFunctionBegin; 9333 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9334 PetscAssertPointer(set, 2); 9335 PetscAssertPointer(flg, 3); 9336 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9337 *set = PETSC_TRUE; 9338 *flg = PetscBool3ToBool(A->symmetric); 9339 } else { 9340 *set = PETSC_FALSE; 9341 } 9342 PetscFunctionReturn(PETSC_SUCCESS); 9343 } 9344 9345 /*@ 9346 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9347 9348 Not Collective 9349 9350 Input Parameter: 9351 . A - the matrix to check 9352 9353 Output Parameters: 9354 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9355 - flg - the result (only valid if set is `PETSC_TRUE`) 9356 9357 Level: advanced 9358 9359 Notes: 9360 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9361 9362 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9363 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9364 9365 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9366 @*/ 9367 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9368 { 9369 PetscFunctionBegin; 9370 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9371 PetscAssertPointer(set, 2); 9372 PetscAssertPointer(flg, 3); 9373 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9374 *set = PETSC_TRUE; 9375 *flg = PetscBool3ToBool(A->spd); 9376 } else { 9377 *set = PETSC_FALSE; 9378 } 9379 PetscFunctionReturn(PETSC_SUCCESS); 9380 } 9381 9382 /*@ 9383 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9384 9385 Not Collective 9386 9387 Input Parameter: 9388 . A - the matrix to check 9389 9390 Output Parameters: 9391 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9392 - flg - the result (only valid if set is `PETSC_TRUE`) 9393 9394 Level: advanced 9395 9396 Notes: 9397 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9398 if you want it explicitly checked 9399 9400 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9401 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9402 9403 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9404 @*/ 9405 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9406 { 9407 PetscFunctionBegin; 9408 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9409 PetscAssertPointer(set, 2); 9410 PetscAssertPointer(flg, 3); 9411 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9412 *set = PETSC_TRUE; 9413 *flg = PetscBool3ToBool(A->hermitian); 9414 } else { 9415 *set = PETSC_FALSE; 9416 } 9417 PetscFunctionReturn(PETSC_SUCCESS); 9418 } 9419 9420 /*@ 9421 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9422 9423 Collective 9424 9425 Input Parameter: 9426 . A - the matrix to test 9427 9428 Output Parameter: 9429 . flg - the result 9430 9431 Level: intermediate 9432 9433 Notes: 9434 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9435 9436 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 9437 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9438 9439 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9440 @*/ 9441 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9442 { 9443 PetscFunctionBegin; 9444 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9445 PetscAssertPointer(flg, 2); 9446 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9447 *flg = PetscBool3ToBool(A->structurally_symmetric); 9448 } else { 9449 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9450 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9451 } 9452 PetscFunctionReturn(PETSC_SUCCESS); 9453 } 9454 9455 /*@ 9456 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9457 9458 Not Collective 9459 9460 Input Parameter: 9461 . A - the matrix to check 9462 9463 Output Parameters: 9464 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9465 - flg - the result (only valid if set is PETSC_TRUE) 9466 9467 Level: advanced 9468 9469 Notes: 9470 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 9471 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9472 9473 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9474 9475 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9476 @*/ 9477 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9478 { 9479 PetscFunctionBegin; 9480 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9481 PetscAssertPointer(set, 2); 9482 PetscAssertPointer(flg, 3); 9483 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9484 *set = PETSC_TRUE; 9485 *flg = PetscBool3ToBool(A->structurally_symmetric); 9486 } else { 9487 *set = PETSC_FALSE; 9488 } 9489 PetscFunctionReturn(PETSC_SUCCESS); 9490 } 9491 9492 /*@ 9493 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9494 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9495 9496 Not Collective 9497 9498 Input Parameter: 9499 . mat - the matrix 9500 9501 Output Parameters: 9502 + nstash - the size of the stash 9503 . reallocs - the number of additional mallocs incurred. 9504 . bnstash - the size of the block stash 9505 - breallocs - the number of additional mallocs incurred.in the block stash 9506 9507 Level: advanced 9508 9509 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9510 @*/ 9511 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9512 { 9513 PetscFunctionBegin; 9514 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9515 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9516 PetscFunctionReturn(PETSC_SUCCESS); 9517 } 9518 9519 /*@ 9520 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9521 parallel layout, `PetscLayout` for rows and columns 9522 9523 Collective 9524 9525 Input Parameter: 9526 . mat - the matrix 9527 9528 Output Parameters: 9529 + right - (optional) vector that the matrix can be multiplied against 9530 - left - (optional) vector that the matrix vector product can be stored in 9531 9532 Level: advanced 9533 9534 Notes: 9535 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()`. 9536 9537 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9538 9539 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9540 @*/ 9541 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9542 { 9543 PetscFunctionBegin; 9544 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9545 PetscValidType(mat, 1); 9546 if (mat->ops->getvecs) { 9547 PetscUseTypeMethod(mat, getvecs, right, left); 9548 } else { 9549 if (right) { 9550 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9551 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9552 PetscCall(VecSetType(*right, mat->defaultvectype)); 9553 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9554 if (mat->boundtocpu && mat->bindingpropagates) { 9555 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9556 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9557 } 9558 #endif 9559 } 9560 if (left) { 9561 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9562 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9563 PetscCall(VecSetType(*left, mat->defaultvectype)); 9564 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9565 if (mat->boundtocpu && mat->bindingpropagates) { 9566 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9567 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9568 } 9569 #endif 9570 } 9571 } 9572 PetscFunctionReturn(PETSC_SUCCESS); 9573 } 9574 9575 /*@ 9576 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9577 with default values. 9578 9579 Not Collective 9580 9581 Input Parameter: 9582 . info - the `MatFactorInfo` data structure 9583 9584 Level: developer 9585 9586 Notes: 9587 The solvers are generally used through the `KSP` and `PC` objects, for example 9588 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9589 9590 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9591 9592 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9593 @*/ 9594 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9595 { 9596 PetscFunctionBegin; 9597 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9598 PetscFunctionReturn(PETSC_SUCCESS); 9599 } 9600 9601 /*@ 9602 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9603 9604 Collective 9605 9606 Input Parameters: 9607 + mat - the factored matrix 9608 - is - the index set defining the Schur indices (0-based) 9609 9610 Level: advanced 9611 9612 Notes: 9613 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9614 9615 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9616 9617 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9618 9619 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9620 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9621 @*/ 9622 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9623 { 9624 PetscErrorCode (*f)(Mat, IS); 9625 9626 PetscFunctionBegin; 9627 PetscValidType(mat, 1); 9628 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9629 PetscValidType(is, 2); 9630 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9631 PetscCheckSameComm(mat, 1, is, 2); 9632 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9633 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9634 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9635 PetscCall(MatDestroy(&mat->schur)); 9636 PetscCall((*f)(mat, is)); 9637 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9638 PetscFunctionReturn(PETSC_SUCCESS); 9639 } 9640 9641 /*@ 9642 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9643 9644 Logically Collective 9645 9646 Input Parameters: 9647 + F - the factored matrix obtained by calling `MatGetFactor()` 9648 . S - location where to return the Schur complement, can be `NULL` 9649 - status - the status of the Schur complement matrix, can be `NULL` 9650 9651 Level: advanced 9652 9653 Notes: 9654 You must call `MatFactorSetSchurIS()` before calling this routine. 9655 9656 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9657 9658 The routine provides a copy of the Schur matrix stored within the solver data structures. 9659 The caller must destroy the object when it is no longer needed. 9660 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9661 9662 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) 9663 9664 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9665 9666 Developer Note: 9667 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9668 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9669 9670 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9671 @*/ 9672 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9673 { 9674 PetscFunctionBegin; 9675 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9676 if (S) PetscAssertPointer(S, 2); 9677 if (status) PetscAssertPointer(status, 3); 9678 if (S) { 9679 PetscErrorCode (*f)(Mat, Mat *); 9680 9681 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9682 if (f) { 9683 PetscCall((*f)(F, S)); 9684 } else { 9685 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9686 } 9687 } 9688 if (status) *status = F->schur_status; 9689 PetscFunctionReturn(PETSC_SUCCESS); 9690 } 9691 9692 /*@ 9693 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9694 9695 Logically Collective 9696 9697 Input Parameters: 9698 + F - the factored matrix obtained by calling `MatGetFactor()` 9699 . S - location where to return the Schur complement, can be `NULL` 9700 - status - the status of the Schur complement matrix, can be `NULL` 9701 9702 Level: advanced 9703 9704 Notes: 9705 You must call `MatFactorSetSchurIS()` before calling this routine. 9706 9707 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9708 9709 The routine returns a the Schur Complement stored within the data structures of the solver. 9710 9711 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9712 9713 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9714 9715 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9716 9717 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9718 9719 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9720 @*/ 9721 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9722 { 9723 PetscFunctionBegin; 9724 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9725 if (S) { 9726 PetscAssertPointer(S, 2); 9727 *S = F->schur; 9728 } 9729 if (status) { 9730 PetscAssertPointer(status, 3); 9731 *status = F->schur_status; 9732 } 9733 PetscFunctionReturn(PETSC_SUCCESS); 9734 } 9735 9736 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9737 { 9738 Mat S = F->schur; 9739 9740 PetscFunctionBegin; 9741 switch (F->schur_status) { 9742 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9743 case MAT_FACTOR_SCHUR_INVERTED: 9744 if (S) { 9745 S->ops->solve = NULL; 9746 S->ops->matsolve = NULL; 9747 S->ops->solvetranspose = NULL; 9748 S->ops->matsolvetranspose = NULL; 9749 S->ops->solveadd = NULL; 9750 S->ops->solvetransposeadd = NULL; 9751 S->factortype = MAT_FACTOR_NONE; 9752 PetscCall(PetscFree(S->solvertype)); 9753 } 9754 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9755 break; 9756 default: 9757 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9758 } 9759 PetscFunctionReturn(PETSC_SUCCESS); 9760 } 9761 9762 /*@ 9763 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9764 9765 Logically Collective 9766 9767 Input Parameters: 9768 + F - the factored matrix obtained by calling `MatGetFactor()` 9769 . S - location where the Schur complement is stored 9770 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9771 9772 Level: advanced 9773 9774 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9775 @*/ 9776 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9777 { 9778 PetscFunctionBegin; 9779 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9780 if (S) { 9781 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9782 *S = NULL; 9783 } 9784 F->schur_status = status; 9785 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9786 PetscFunctionReturn(PETSC_SUCCESS); 9787 } 9788 9789 /*@ 9790 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9791 9792 Logically Collective 9793 9794 Input Parameters: 9795 + F - the factored matrix obtained by calling `MatGetFactor()` 9796 . rhs - location where the right-hand side of the Schur complement system is stored 9797 - sol - location where the solution of the Schur complement system has to be returned 9798 9799 Level: advanced 9800 9801 Notes: 9802 The sizes of the vectors should match the size of the Schur complement 9803 9804 Must be called after `MatFactorSetSchurIS()` 9805 9806 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9807 @*/ 9808 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9809 { 9810 PetscFunctionBegin; 9811 PetscValidType(F, 1); 9812 PetscValidType(rhs, 2); 9813 PetscValidType(sol, 3); 9814 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9815 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9816 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9817 PetscCheckSameComm(F, 1, rhs, 2); 9818 PetscCheckSameComm(F, 1, sol, 3); 9819 PetscCall(MatFactorFactorizeSchurComplement(F)); 9820 switch (F->schur_status) { 9821 case MAT_FACTOR_SCHUR_FACTORED: 9822 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9823 break; 9824 case MAT_FACTOR_SCHUR_INVERTED: 9825 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9826 break; 9827 default: 9828 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9829 } 9830 PetscFunctionReturn(PETSC_SUCCESS); 9831 } 9832 9833 /*@ 9834 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9835 9836 Logically Collective 9837 9838 Input Parameters: 9839 + F - the factored matrix obtained by calling `MatGetFactor()` 9840 . rhs - location where the right-hand side of the Schur complement system is stored 9841 - sol - location where the solution of the Schur complement system has to be returned 9842 9843 Level: advanced 9844 9845 Notes: 9846 The sizes of the vectors should match the size of the Schur complement 9847 9848 Must be called after `MatFactorSetSchurIS()` 9849 9850 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9851 @*/ 9852 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9853 { 9854 PetscFunctionBegin; 9855 PetscValidType(F, 1); 9856 PetscValidType(rhs, 2); 9857 PetscValidType(sol, 3); 9858 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9859 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9860 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9861 PetscCheckSameComm(F, 1, rhs, 2); 9862 PetscCheckSameComm(F, 1, sol, 3); 9863 PetscCall(MatFactorFactorizeSchurComplement(F)); 9864 switch (F->schur_status) { 9865 case MAT_FACTOR_SCHUR_FACTORED: 9866 PetscCall(MatSolve(F->schur, rhs, sol)); 9867 break; 9868 case MAT_FACTOR_SCHUR_INVERTED: 9869 PetscCall(MatMult(F->schur, rhs, sol)); 9870 break; 9871 default: 9872 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9873 } 9874 PetscFunctionReturn(PETSC_SUCCESS); 9875 } 9876 9877 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9878 #if PetscDefined(HAVE_CUDA) 9879 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9880 #endif 9881 9882 /* Schur status updated in the interface */ 9883 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9884 { 9885 Mat S = F->schur; 9886 9887 PetscFunctionBegin; 9888 if (S) { 9889 PetscMPIInt size; 9890 PetscBool isdense, isdensecuda; 9891 9892 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9893 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9894 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9895 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9896 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9897 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9898 if (isdense) { 9899 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9900 } else if (isdensecuda) { 9901 #if defined(PETSC_HAVE_CUDA) 9902 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9903 #endif 9904 } 9905 // HIP?????????????? 9906 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9907 } 9908 PetscFunctionReturn(PETSC_SUCCESS); 9909 } 9910 9911 /*@ 9912 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9913 9914 Logically Collective 9915 9916 Input Parameter: 9917 . F - the factored matrix obtained by calling `MatGetFactor()` 9918 9919 Level: advanced 9920 9921 Notes: 9922 Must be called after `MatFactorSetSchurIS()`. 9923 9924 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9925 9926 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9927 @*/ 9928 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9929 { 9930 PetscFunctionBegin; 9931 PetscValidType(F, 1); 9932 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9933 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9934 PetscCall(MatFactorFactorizeSchurComplement(F)); 9935 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9936 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9937 PetscFunctionReturn(PETSC_SUCCESS); 9938 } 9939 9940 /*@ 9941 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9942 9943 Logically Collective 9944 9945 Input Parameter: 9946 . F - the factored matrix obtained by calling `MatGetFactor()` 9947 9948 Level: advanced 9949 9950 Note: 9951 Must be called after `MatFactorSetSchurIS()` 9952 9953 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9954 @*/ 9955 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9956 { 9957 MatFactorInfo info; 9958 9959 PetscFunctionBegin; 9960 PetscValidType(F, 1); 9961 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9962 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9963 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9964 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9965 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9966 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9967 } else { 9968 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9969 } 9970 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9971 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9972 PetscFunctionReturn(PETSC_SUCCESS); 9973 } 9974 9975 /*@ 9976 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9977 9978 Neighbor-wise Collective 9979 9980 Input Parameters: 9981 + A - the matrix 9982 . P - the projection matrix 9983 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9984 - 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 9985 if the result is a dense matrix this is irrelevant 9986 9987 Output Parameter: 9988 . C - the product matrix 9989 9990 Level: intermediate 9991 9992 Notes: 9993 C will be created and must be destroyed by the user with `MatDestroy()`. 9994 9995 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9996 9997 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 9998 9999 Developer Note: 10000 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10001 10002 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10003 @*/ 10004 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10005 { 10006 PetscFunctionBegin; 10007 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10008 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10009 10010 if (scall == MAT_INITIAL_MATRIX) { 10011 PetscCall(MatProductCreate(A, P, NULL, C)); 10012 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10013 PetscCall(MatProductSetAlgorithm(*C, "default")); 10014 PetscCall(MatProductSetFill(*C, fill)); 10015 10016 (*C)->product->api_user = PETSC_TRUE; 10017 PetscCall(MatProductSetFromOptions(*C)); 10018 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); 10019 PetscCall(MatProductSymbolic(*C)); 10020 } else { /* scall == MAT_REUSE_MATRIX */ 10021 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10022 } 10023 10024 PetscCall(MatProductNumeric(*C)); 10025 (*C)->symmetric = A->symmetric; 10026 (*C)->spd = A->spd; 10027 PetscFunctionReturn(PETSC_SUCCESS); 10028 } 10029 10030 /*@ 10031 MatRARt - Creates the matrix product $C = R * A * R^T$ 10032 10033 Neighbor-wise Collective 10034 10035 Input Parameters: 10036 + A - the matrix 10037 . R - the projection matrix 10038 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10039 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10040 if the result is a dense matrix this is irrelevant 10041 10042 Output Parameter: 10043 . C - the product matrix 10044 10045 Level: intermediate 10046 10047 Notes: 10048 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10049 10050 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10051 10052 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10053 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10054 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10055 We recommend using `MatPtAP()` when possible. 10056 10057 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10058 10059 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10060 @*/ 10061 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10062 { 10063 PetscFunctionBegin; 10064 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10065 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10066 10067 if (scall == MAT_INITIAL_MATRIX) { 10068 PetscCall(MatProductCreate(A, R, NULL, C)); 10069 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10070 PetscCall(MatProductSetAlgorithm(*C, "default")); 10071 PetscCall(MatProductSetFill(*C, fill)); 10072 10073 (*C)->product->api_user = PETSC_TRUE; 10074 PetscCall(MatProductSetFromOptions(*C)); 10075 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); 10076 PetscCall(MatProductSymbolic(*C)); 10077 } else { /* scall == MAT_REUSE_MATRIX */ 10078 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10079 } 10080 10081 PetscCall(MatProductNumeric(*C)); 10082 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10083 PetscFunctionReturn(PETSC_SUCCESS); 10084 } 10085 10086 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10087 { 10088 PetscBool flg = PETSC_TRUE; 10089 10090 PetscFunctionBegin; 10091 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10092 if (scall == MAT_INITIAL_MATRIX) { 10093 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10094 PetscCall(MatProductCreate(A, B, NULL, C)); 10095 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10096 PetscCall(MatProductSetFill(*C, fill)); 10097 } else { /* scall == MAT_REUSE_MATRIX */ 10098 Mat_Product *product = (*C)->product; 10099 10100 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10101 if (flg && product && product->type != ptype) { 10102 PetscCall(MatProductClear(*C)); 10103 product = NULL; 10104 } 10105 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10106 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10107 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10108 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10109 product = (*C)->product; 10110 product->fill = fill; 10111 product->clear = PETSC_TRUE; 10112 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10113 flg = PETSC_FALSE; 10114 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10115 } 10116 } 10117 if (flg) { 10118 (*C)->product->api_user = PETSC_TRUE; 10119 PetscCall(MatProductSetType(*C, ptype)); 10120 PetscCall(MatProductSetFromOptions(*C)); 10121 PetscCall(MatProductSymbolic(*C)); 10122 } 10123 PetscCall(MatProductNumeric(*C)); 10124 PetscFunctionReturn(PETSC_SUCCESS); 10125 } 10126 10127 /*@ 10128 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10129 10130 Neighbor-wise Collective 10131 10132 Input Parameters: 10133 + A - the left matrix 10134 . B - the right matrix 10135 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10136 - 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 10137 if the result is a dense matrix this is irrelevant 10138 10139 Output Parameter: 10140 . C - the product matrix 10141 10142 Notes: 10143 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10144 10145 `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 10146 call to this function with `MAT_INITIAL_MATRIX`. 10147 10148 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10149 10150 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`, 10151 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10152 10153 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10154 10155 Example of Usage: 10156 .vb 10157 MatProductCreate(A,B,NULL,&C); 10158 MatProductSetType(C,MATPRODUCT_AB); 10159 MatProductSymbolic(C); 10160 MatProductNumeric(C); // compute C=A * B 10161 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10162 MatProductNumeric(C); 10163 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10164 MatProductNumeric(C); 10165 .ve 10166 10167 Level: intermediate 10168 10169 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10170 @*/ 10171 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10172 { 10173 PetscFunctionBegin; 10174 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10175 PetscFunctionReturn(PETSC_SUCCESS); 10176 } 10177 10178 /*@ 10179 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10180 10181 Neighbor-wise Collective 10182 10183 Input Parameters: 10184 + A - the left matrix 10185 . B - the right matrix 10186 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10187 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10188 10189 Output Parameter: 10190 . C - the product matrix 10191 10192 Options Database Key: 10193 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10194 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10195 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10196 10197 Level: intermediate 10198 10199 Notes: 10200 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10201 10202 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10203 10204 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10205 actually needed. 10206 10207 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10208 and for pairs of `MATMPIDENSE` matrices. 10209 10210 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10211 10212 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10213 10214 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10215 @*/ 10216 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10217 { 10218 PetscFunctionBegin; 10219 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10220 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10221 PetscFunctionReturn(PETSC_SUCCESS); 10222 } 10223 10224 /*@ 10225 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10226 10227 Neighbor-wise Collective 10228 10229 Input Parameters: 10230 + A - the left matrix 10231 . B - the right matrix 10232 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10233 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10234 10235 Output Parameter: 10236 . C - the product matrix 10237 10238 Level: intermediate 10239 10240 Notes: 10241 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10242 10243 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10244 10245 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10246 10247 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10248 actually needed. 10249 10250 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10251 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10252 10253 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10254 10255 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10256 @*/ 10257 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10258 { 10259 PetscFunctionBegin; 10260 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10261 PetscFunctionReturn(PETSC_SUCCESS); 10262 } 10263 10264 /*@ 10265 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10266 10267 Neighbor-wise Collective 10268 10269 Input Parameters: 10270 + A - the left matrix 10271 . B - the middle matrix 10272 . C - the right matrix 10273 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10274 - 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 10275 if the result is a dense matrix this is irrelevant 10276 10277 Output Parameter: 10278 . D - the product matrix 10279 10280 Level: intermediate 10281 10282 Notes: 10283 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10284 10285 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10286 10287 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10288 10289 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10290 actually needed. 10291 10292 If you have many matrices with the same non-zero structure to multiply, you 10293 should use `MAT_REUSE_MATRIX` in all calls but the first 10294 10295 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10296 10297 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10298 @*/ 10299 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10300 { 10301 PetscFunctionBegin; 10302 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10303 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10304 10305 if (scall == MAT_INITIAL_MATRIX) { 10306 PetscCall(MatProductCreate(A, B, C, D)); 10307 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10308 PetscCall(MatProductSetAlgorithm(*D, "default")); 10309 PetscCall(MatProductSetFill(*D, fill)); 10310 10311 (*D)->product->api_user = PETSC_TRUE; 10312 PetscCall(MatProductSetFromOptions(*D)); 10313 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, 10314 ((PetscObject)C)->type_name); 10315 PetscCall(MatProductSymbolic(*D)); 10316 } else { /* user may change input matrices when REUSE */ 10317 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10318 } 10319 PetscCall(MatProductNumeric(*D)); 10320 PetscFunctionReturn(PETSC_SUCCESS); 10321 } 10322 10323 /*@ 10324 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10325 10326 Collective 10327 10328 Input Parameters: 10329 + mat - the matrix 10330 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10331 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10332 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10333 10334 Output Parameter: 10335 . matredundant - redundant matrix 10336 10337 Level: advanced 10338 10339 Notes: 10340 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10341 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10342 10343 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10344 calling it. 10345 10346 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10347 10348 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10349 @*/ 10350 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10351 { 10352 MPI_Comm comm; 10353 PetscMPIInt size; 10354 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10355 Mat_Redundant *redund = NULL; 10356 PetscSubcomm psubcomm = NULL; 10357 MPI_Comm subcomm_in = subcomm; 10358 Mat *matseq; 10359 IS isrow, iscol; 10360 PetscBool newsubcomm = PETSC_FALSE; 10361 10362 PetscFunctionBegin; 10363 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10364 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10365 PetscAssertPointer(*matredundant, 5); 10366 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10367 } 10368 10369 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10370 if (size == 1 || nsubcomm == 1) { 10371 if (reuse == MAT_INITIAL_MATRIX) { 10372 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10373 } else { 10374 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"); 10375 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10376 } 10377 PetscFunctionReturn(PETSC_SUCCESS); 10378 } 10379 10380 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10381 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10382 MatCheckPreallocated(mat, 1); 10383 10384 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10385 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10386 /* create psubcomm, then get subcomm */ 10387 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10388 PetscCallMPI(MPI_Comm_size(comm, &size)); 10389 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10390 10391 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10392 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10393 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10394 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10395 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10396 newsubcomm = PETSC_TRUE; 10397 PetscCall(PetscSubcommDestroy(&psubcomm)); 10398 } 10399 10400 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10401 if (reuse == MAT_INITIAL_MATRIX) { 10402 mloc_sub = PETSC_DECIDE; 10403 nloc_sub = PETSC_DECIDE; 10404 if (bs < 1) { 10405 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10406 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10407 } else { 10408 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10409 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10410 } 10411 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10412 rstart = rend - mloc_sub; 10413 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10414 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10415 PetscCall(ISSetIdentity(iscol)); 10416 } else { /* reuse == MAT_REUSE_MATRIX */ 10417 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"); 10418 /* retrieve subcomm */ 10419 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10420 redund = (*matredundant)->redundant; 10421 isrow = redund->isrow; 10422 iscol = redund->iscol; 10423 matseq = redund->matseq; 10424 } 10425 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10426 10427 /* get matredundant over subcomm */ 10428 if (reuse == MAT_INITIAL_MATRIX) { 10429 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10430 10431 /* create a supporting struct and attach it to C for reuse */ 10432 PetscCall(PetscNew(&redund)); 10433 (*matredundant)->redundant = redund; 10434 redund->isrow = isrow; 10435 redund->iscol = iscol; 10436 redund->matseq = matseq; 10437 if (newsubcomm) { 10438 redund->subcomm = subcomm; 10439 } else { 10440 redund->subcomm = MPI_COMM_NULL; 10441 } 10442 } else { 10443 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10444 } 10445 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10446 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10447 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10448 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10449 } 10450 #endif 10451 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10452 PetscFunctionReturn(PETSC_SUCCESS); 10453 } 10454 10455 /*@C 10456 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10457 a given `Mat`. Each submatrix can span multiple procs. 10458 10459 Collective 10460 10461 Input Parameters: 10462 + mat - the matrix 10463 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10464 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10465 10466 Output Parameter: 10467 . subMat - parallel sub-matrices each spanning a given `subcomm` 10468 10469 Level: advanced 10470 10471 Notes: 10472 The submatrix partition across processors is dictated by `subComm` a 10473 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10474 is not restricted to be grouped with consecutive original MPI processes. 10475 10476 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10477 map directly to the layout of the original matrix [wrt the local 10478 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10479 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10480 the `subMat`. However the offDiagMat looses some columns - and this is 10481 reconstructed with `MatSetValues()` 10482 10483 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10484 10485 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10486 @*/ 10487 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10488 { 10489 PetscMPIInt commsize, subCommSize; 10490 10491 PetscFunctionBegin; 10492 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10493 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10494 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10495 10496 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"); 10497 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10498 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10499 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10500 PetscFunctionReturn(PETSC_SUCCESS); 10501 } 10502 10503 /*@ 10504 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10505 10506 Not Collective 10507 10508 Input Parameters: 10509 + mat - matrix to extract local submatrix from 10510 . isrow - local row indices for submatrix 10511 - iscol - local column indices for submatrix 10512 10513 Output Parameter: 10514 . submat - the submatrix 10515 10516 Level: intermediate 10517 10518 Notes: 10519 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10520 10521 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10522 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10523 10524 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10525 `MatSetValuesBlockedLocal()` will also be implemented. 10526 10527 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10528 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10529 10530 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10531 @*/ 10532 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10533 { 10534 PetscFunctionBegin; 10535 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10536 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10537 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10538 PetscCheckSameComm(isrow, 2, iscol, 3); 10539 PetscAssertPointer(submat, 4); 10540 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10541 10542 if (mat->ops->getlocalsubmatrix) { 10543 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10544 } else { 10545 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10546 } 10547 PetscFunctionReturn(PETSC_SUCCESS); 10548 } 10549 10550 /*@ 10551 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10552 10553 Not Collective 10554 10555 Input Parameters: 10556 + mat - matrix to extract local submatrix from 10557 . isrow - local row indices for submatrix 10558 . iscol - local column indices for submatrix 10559 - submat - the submatrix 10560 10561 Level: intermediate 10562 10563 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10564 @*/ 10565 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10566 { 10567 PetscFunctionBegin; 10568 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10569 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10570 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10571 PetscCheckSameComm(isrow, 2, iscol, 3); 10572 PetscAssertPointer(submat, 4); 10573 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10574 10575 if (mat->ops->restorelocalsubmatrix) { 10576 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10577 } else { 10578 PetscCall(MatDestroy(submat)); 10579 } 10580 *submat = NULL; 10581 PetscFunctionReturn(PETSC_SUCCESS); 10582 } 10583 10584 /*@ 10585 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10586 10587 Collective 10588 10589 Input Parameter: 10590 . mat - the matrix 10591 10592 Output Parameter: 10593 . is - if any rows have zero diagonals this contains the list of them 10594 10595 Level: developer 10596 10597 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10598 @*/ 10599 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10600 { 10601 PetscFunctionBegin; 10602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10603 PetscValidType(mat, 1); 10604 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10605 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10606 10607 if (!mat->ops->findzerodiagonals) { 10608 Vec diag; 10609 const PetscScalar *a; 10610 PetscInt *rows; 10611 PetscInt rStart, rEnd, r, nrow = 0; 10612 10613 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10614 PetscCall(MatGetDiagonal(mat, diag)); 10615 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10616 PetscCall(VecGetArrayRead(diag, &a)); 10617 for (r = 0; r < rEnd - rStart; ++r) 10618 if (a[r] == 0.0) ++nrow; 10619 PetscCall(PetscMalloc1(nrow, &rows)); 10620 nrow = 0; 10621 for (r = 0; r < rEnd - rStart; ++r) 10622 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10623 PetscCall(VecRestoreArrayRead(diag, &a)); 10624 PetscCall(VecDestroy(&diag)); 10625 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10626 } else { 10627 PetscUseTypeMethod(mat, findzerodiagonals, is); 10628 } 10629 PetscFunctionReturn(PETSC_SUCCESS); 10630 } 10631 10632 /*@ 10633 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10634 10635 Collective 10636 10637 Input Parameter: 10638 . mat - the matrix 10639 10640 Output Parameter: 10641 . is - contains the list of rows with off block diagonal entries 10642 10643 Level: developer 10644 10645 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10646 @*/ 10647 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10648 { 10649 PetscFunctionBegin; 10650 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10651 PetscValidType(mat, 1); 10652 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10653 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10654 10655 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10656 PetscFunctionReturn(PETSC_SUCCESS); 10657 } 10658 10659 /*@C 10660 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10661 10662 Collective; No Fortran Support 10663 10664 Input Parameter: 10665 . mat - the matrix 10666 10667 Output Parameter: 10668 . values - the block inverses in column major order (FORTRAN-like) 10669 10670 Level: advanced 10671 10672 Notes: 10673 The size of the blocks is determined by the block size of the matrix. 10674 10675 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10676 10677 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10678 10679 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10680 @*/ 10681 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10682 { 10683 PetscFunctionBegin; 10684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10685 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10686 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10687 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10688 PetscFunctionReturn(PETSC_SUCCESS); 10689 } 10690 10691 /*@ 10692 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10693 10694 Collective; No Fortran Support 10695 10696 Input Parameters: 10697 + mat - the matrix 10698 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10699 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10700 10701 Output Parameter: 10702 . values - the block inverses in column major order (FORTRAN-like) 10703 10704 Level: advanced 10705 10706 Notes: 10707 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10708 10709 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10710 10711 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10712 @*/ 10713 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10714 { 10715 PetscFunctionBegin; 10716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10717 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10718 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10719 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10720 PetscFunctionReturn(PETSC_SUCCESS); 10721 } 10722 10723 /*@ 10724 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10725 10726 Collective 10727 10728 Input Parameters: 10729 + A - the matrix 10730 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10731 10732 Level: advanced 10733 10734 Note: 10735 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10736 10737 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10738 @*/ 10739 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10740 { 10741 const PetscScalar *vals; 10742 PetscInt *dnnz; 10743 PetscInt m, rstart, rend, bs, i, j; 10744 10745 PetscFunctionBegin; 10746 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10747 PetscCall(MatGetBlockSize(A, &bs)); 10748 PetscCall(MatGetLocalSize(A, &m, NULL)); 10749 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10750 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10751 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10752 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10753 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10754 PetscCall(PetscFree(dnnz)); 10755 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10756 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10757 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10758 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10759 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10760 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10761 PetscFunctionReturn(PETSC_SUCCESS); 10762 } 10763 10764 /*@ 10765 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10766 via `MatTransposeColoringCreate()`. 10767 10768 Collective 10769 10770 Input Parameter: 10771 . c - coloring context 10772 10773 Level: intermediate 10774 10775 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10776 @*/ 10777 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10778 { 10779 MatTransposeColoring matcolor = *c; 10780 10781 PetscFunctionBegin; 10782 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10783 if (--((PetscObject)matcolor)->refct > 0) { 10784 matcolor = NULL; 10785 PetscFunctionReturn(PETSC_SUCCESS); 10786 } 10787 10788 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10789 PetscCall(PetscFree(matcolor->rows)); 10790 PetscCall(PetscFree(matcolor->den2sp)); 10791 PetscCall(PetscFree(matcolor->colorforcol)); 10792 PetscCall(PetscFree(matcolor->columns)); 10793 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10794 PetscCall(PetscHeaderDestroy(c)); 10795 PetscFunctionReturn(PETSC_SUCCESS); 10796 } 10797 10798 /*@ 10799 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10800 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10801 `MatTransposeColoring` to sparse `B`. 10802 10803 Collective 10804 10805 Input Parameters: 10806 + coloring - coloring context created with `MatTransposeColoringCreate()` 10807 - B - sparse matrix 10808 10809 Output Parameter: 10810 . Btdense - dense matrix $B^T$ 10811 10812 Level: developer 10813 10814 Note: 10815 These are used internally for some implementations of `MatRARt()` 10816 10817 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10818 @*/ 10819 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10820 { 10821 PetscFunctionBegin; 10822 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10823 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10824 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10825 10826 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10827 PetscFunctionReturn(PETSC_SUCCESS); 10828 } 10829 10830 /*@ 10831 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10832 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10833 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10834 $C_{sp}$ from $C_{den}$. 10835 10836 Collective 10837 10838 Input Parameters: 10839 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10840 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10841 10842 Output Parameter: 10843 . Csp - sparse matrix 10844 10845 Level: developer 10846 10847 Note: 10848 These are used internally for some implementations of `MatRARt()` 10849 10850 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10851 @*/ 10852 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10853 { 10854 PetscFunctionBegin; 10855 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10856 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10857 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10858 10859 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10860 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10861 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10862 PetscFunctionReturn(PETSC_SUCCESS); 10863 } 10864 10865 /*@ 10866 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10867 10868 Collective 10869 10870 Input Parameters: 10871 + mat - the matrix product C 10872 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10873 10874 Output Parameter: 10875 . color - the new coloring context 10876 10877 Level: intermediate 10878 10879 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10880 `MatTransColoringApplyDenToSp()` 10881 @*/ 10882 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10883 { 10884 MatTransposeColoring c; 10885 MPI_Comm comm; 10886 10887 PetscFunctionBegin; 10888 PetscAssertPointer(color, 3); 10889 10890 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10891 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10892 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10893 c->ctype = iscoloring->ctype; 10894 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10895 *color = c; 10896 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10897 PetscFunctionReturn(PETSC_SUCCESS); 10898 } 10899 10900 /*@ 10901 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10902 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10903 10904 Not Collective 10905 10906 Input Parameter: 10907 . mat - the matrix 10908 10909 Output Parameter: 10910 . state - the current state 10911 10912 Level: intermediate 10913 10914 Notes: 10915 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10916 different matrices 10917 10918 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10919 10920 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10921 10922 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10923 @*/ 10924 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10925 { 10926 PetscFunctionBegin; 10927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10928 *state = mat->nonzerostate; 10929 PetscFunctionReturn(PETSC_SUCCESS); 10930 } 10931 10932 /*@ 10933 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10934 matrices from each processor 10935 10936 Collective 10937 10938 Input Parameters: 10939 + comm - the communicators the parallel matrix will live on 10940 . seqmat - the input sequential matrices 10941 . n - number of local columns (or `PETSC_DECIDE`) 10942 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10943 10944 Output Parameter: 10945 . mpimat - the parallel matrix generated 10946 10947 Level: developer 10948 10949 Note: 10950 The number of columns of the matrix in EACH processor MUST be the same. 10951 10952 .seealso: [](ch_matrices), `Mat` 10953 @*/ 10954 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10955 { 10956 PetscMPIInt size; 10957 10958 PetscFunctionBegin; 10959 PetscCallMPI(MPI_Comm_size(comm, &size)); 10960 if (size == 1) { 10961 if (reuse == MAT_INITIAL_MATRIX) { 10962 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10963 } else { 10964 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10965 } 10966 PetscFunctionReturn(PETSC_SUCCESS); 10967 } 10968 10969 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"); 10970 10971 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10972 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10973 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10974 PetscFunctionReturn(PETSC_SUCCESS); 10975 } 10976 10977 /*@ 10978 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10979 10980 Collective 10981 10982 Input Parameters: 10983 + A - the matrix to create subdomains from 10984 - N - requested number of subdomains 10985 10986 Output Parameters: 10987 + n - number of subdomains resulting on this MPI process 10988 - iss - `IS` list with indices of subdomains on this MPI process 10989 10990 Level: advanced 10991 10992 Note: 10993 The number of subdomains must be smaller than the communicator size 10994 10995 .seealso: [](ch_matrices), `Mat`, `IS` 10996 @*/ 10997 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10998 { 10999 MPI_Comm comm, subcomm; 11000 PetscMPIInt size, rank, color; 11001 PetscInt rstart, rend, k; 11002 11003 PetscFunctionBegin; 11004 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11005 PetscCallMPI(MPI_Comm_size(comm, &size)); 11006 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11007 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); 11008 *n = 1; 11009 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11010 color = rank / k; 11011 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11012 PetscCall(PetscMalloc1(1, iss)); 11013 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11014 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11015 PetscCallMPI(MPI_Comm_free(&subcomm)); 11016 PetscFunctionReturn(PETSC_SUCCESS); 11017 } 11018 11019 /*@ 11020 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11021 11022 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11023 If they are not the same, uses `MatMatMatMult()`. 11024 11025 Once the coarse grid problem is constructed, correct for interpolation operators 11026 that are not of full rank, which can legitimately happen in the case of non-nested 11027 geometric multigrid. 11028 11029 Input Parameters: 11030 + restrct - restriction operator 11031 . dA - fine grid matrix 11032 . interpolate - interpolation operator 11033 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11034 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11035 11036 Output Parameter: 11037 . A - the Galerkin coarse matrix 11038 11039 Options Database Key: 11040 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11041 11042 Level: developer 11043 11044 Note: 11045 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11046 11047 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11048 @*/ 11049 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11050 { 11051 IS zerorows; 11052 Vec diag; 11053 11054 PetscFunctionBegin; 11055 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11056 /* Construct the coarse grid matrix */ 11057 if (interpolate == restrct) { 11058 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11059 } else { 11060 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11061 } 11062 11063 /* If the interpolation matrix is not of full rank, A will have zero rows. 11064 This can legitimately happen in the case of non-nested geometric multigrid. 11065 In that event, we set the rows of the matrix to the rows of the identity, 11066 ignoring the equations (as the RHS will also be zero). */ 11067 11068 PetscCall(MatFindZeroRows(*A, &zerorows)); 11069 11070 if (zerorows != NULL) { /* if there are any zero rows */ 11071 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11072 PetscCall(MatGetDiagonal(*A, diag)); 11073 PetscCall(VecISSet(diag, zerorows, 1.0)); 11074 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11075 PetscCall(VecDestroy(&diag)); 11076 PetscCall(ISDestroy(&zerorows)); 11077 } 11078 PetscFunctionReturn(PETSC_SUCCESS); 11079 } 11080 11081 /*@C 11082 MatSetOperation - Allows user to set a matrix operation for any matrix type 11083 11084 Logically Collective 11085 11086 Input Parameters: 11087 + mat - the matrix 11088 . op - the name of the operation 11089 - f - the function that provides the operation 11090 11091 Level: developer 11092 11093 Example Usage: 11094 .vb 11095 extern PetscErrorCode usermult(Mat, Vec, Vec); 11096 11097 PetscCall(MatCreateXXX(comm, ..., &A)); 11098 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11099 .ve 11100 11101 Notes: 11102 See the file `include/petscmat.h` for a complete list of matrix 11103 operations, which all have the form MATOP_<OPERATION>, where 11104 <OPERATION> is the name (in all capital letters) of the 11105 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11106 11107 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11108 sequence as the usual matrix interface routines, since they 11109 are intended to be accessed via the usual matrix interface 11110 routines, e.g., 11111 .vb 11112 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11113 .ve 11114 11115 In particular each function MUST return `PETSC_SUCCESS` on success and 11116 nonzero on failure. 11117 11118 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11119 11120 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11121 @*/ 11122 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11123 { 11124 PetscFunctionBegin; 11125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11126 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11127 (((void (**)(void))mat->ops)[op]) = f; 11128 PetscFunctionReturn(PETSC_SUCCESS); 11129 } 11130 11131 /*@C 11132 MatGetOperation - Gets a matrix operation for any matrix type. 11133 11134 Not Collective 11135 11136 Input Parameters: 11137 + mat - the matrix 11138 - op - the name of the operation 11139 11140 Output Parameter: 11141 . f - the function that provides the operation 11142 11143 Level: developer 11144 11145 Example Usage: 11146 .vb 11147 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11148 11149 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11150 .ve 11151 11152 Notes: 11153 See the file include/petscmat.h for a complete list of matrix 11154 operations, which all have the form MATOP_<OPERATION>, where 11155 <OPERATION> is the name (in all capital letters) of the 11156 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11157 11158 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11159 11160 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11161 @*/ 11162 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11163 { 11164 PetscFunctionBegin; 11165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11166 *f = (((void (**)(void))mat->ops)[op]); 11167 PetscFunctionReturn(PETSC_SUCCESS); 11168 } 11169 11170 /*@ 11171 MatHasOperation - Determines whether the given matrix supports the particular operation. 11172 11173 Not Collective 11174 11175 Input Parameters: 11176 + mat - the matrix 11177 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11178 11179 Output Parameter: 11180 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11181 11182 Level: advanced 11183 11184 Note: 11185 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11186 11187 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11188 @*/ 11189 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11190 { 11191 PetscFunctionBegin; 11192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11193 PetscAssertPointer(has, 3); 11194 if (mat->ops->hasoperation) { 11195 PetscUseTypeMethod(mat, hasoperation, op, has); 11196 } else { 11197 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11198 else { 11199 *has = PETSC_FALSE; 11200 if (op == MATOP_CREATE_SUBMATRIX) { 11201 PetscMPIInt size; 11202 11203 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11204 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11205 } 11206 } 11207 } 11208 PetscFunctionReturn(PETSC_SUCCESS); 11209 } 11210 11211 /*@ 11212 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11213 11214 Collective 11215 11216 Input Parameter: 11217 . mat - the matrix 11218 11219 Output Parameter: 11220 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11221 11222 Level: beginner 11223 11224 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11225 @*/ 11226 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11227 { 11228 PetscFunctionBegin; 11229 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11230 PetscValidType(mat, 1); 11231 PetscAssertPointer(cong, 2); 11232 if (!mat->rmap || !mat->cmap) { 11233 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11234 PetscFunctionReturn(PETSC_SUCCESS); 11235 } 11236 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11237 PetscCall(PetscLayoutSetUp(mat->rmap)); 11238 PetscCall(PetscLayoutSetUp(mat->cmap)); 11239 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11240 if (*cong) mat->congruentlayouts = 1; 11241 else mat->congruentlayouts = 0; 11242 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11243 PetscFunctionReturn(PETSC_SUCCESS); 11244 } 11245 11246 PetscErrorCode MatSetInf(Mat A) 11247 { 11248 PetscFunctionBegin; 11249 PetscUseTypeMethod(A, setinf); 11250 PetscFunctionReturn(PETSC_SUCCESS); 11251 } 11252 11253 /*@ 11254 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 11255 and possibly removes small values from the graph structure. 11256 11257 Collective 11258 11259 Input Parameters: 11260 + A - the matrix 11261 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11262 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11263 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11264 . num_idx - size of 'index' array 11265 - index - array of block indices to use for graph strength of connection weight 11266 11267 Output Parameter: 11268 . graph - the resulting graph 11269 11270 Level: advanced 11271 11272 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11273 @*/ 11274 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11275 { 11276 PetscFunctionBegin; 11277 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11278 PetscValidType(A, 1); 11279 PetscValidLogicalCollectiveBool(A, scale, 3); 11280 PetscAssertPointer(graph, 7); 11281 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11282 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11283 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11284 PetscFunctionReturn(PETSC_SUCCESS); 11285 } 11286 11287 /*@ 11288 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11289 meaning the same memory is used for the matrix, and no new memory is allocated. 11290 11291 Collective 11292 11293 Input Parameters: 11294 + A - the matrix 11295 - 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 11296 11297 Level: intermediate 11298 11299 Developer Note: 11300 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11301 of the arrays in the data structure are unneeded. 11302 11303 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11304 @*/ 11305 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11306 { 11307 PetscFunctionBegin; 11308 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11309 PetscUseTypeMethod(A, eliminatezeros, keep); 11310 PetscFunctionReturn(PETSC_SUCCESS); 11311 } 11312