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 The calling sequence is 586 .vb 587 MatGetRow(matrix,row,ncols,cols,values,ierr) 588 Mat matrix (input) 589 PetscInt row (input) 590 PetscInt ncols (output) 591 PetscInt cols(maxcols) (output) 592 PetscScalar values(maxcols) output 593 .ve 594 where maxcols >= maximum nonzeros in any row of the matrix. 595 596 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 597 @*/ 598 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 599 { 600 PetscInt incols; 601 602 PetscFunctionBegin; 603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 604 PetscValidType(mat, 1); 605 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 606 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 607 MatCheckPreallocated(mat, 1); 608 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); 609 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 610 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 611 if (ncols) *ncols = incols; 612 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 613 PetscFunctionReturn(PETSC_SUCCESS); 614 } 615 616 /*@ 617 MatConjugate - replaces the matrix values with their complex conjugates 618 619 Logically Collective 620 621 Input Parameter: 622 . mat - the matrix 623 624 Level: advanced 625 626 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 627 @*/ 628 PetscErrorCode MatConjugate(Mat mat) 629 { 630 PetscFunctionBegin; 631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 632 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 633 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 634 PetscUseTypeMethod(mat, conjugate); 635 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 636 } 637 PetscFunctionReturn(PETSC_SUCCESS); 638 } 639 640 /*@C 641 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 642 643 Not Collective 644 645 Input Parameters: 646 + mat - the matrix 647 . row - the row to get 648 . ncols - the number of nonzeros 649 . cols - the columns of the nonzeros 650 - vals - if nonzero the column values 651 652 Level: advanced 653 654 Notes: 655 This routine should be called after you have finished examining the entries. 656 657 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 658 us of the array after it has been restored. If you pass `NULL`, it will 659 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 660 661 Fortran Note: 662 `MatRestoreRow()` MUST be called after `MatGetRow()` 663 before another call to `MatGetRow()` can be made. 664 665 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 666 @*/ 667 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 668 { 669 PetscFunctionBegin; 670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 671 if (ncols) PetscAssertPointer(ncols, 3); 672 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 673 if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS); 674 PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 675 if (ncols) *ncols = 0; 676 if (cols) *cols = NULL; 677 if (vals) *vals = NULL; 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /*@ 682 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 683 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 684 685 Not Collective 686 687 Input Parameter: 688 . mat - the matrix 689 690 Level: advanced 691 692 Note: 693 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. 694 695 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 696 @*/ 697 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 698 { 699 PetscFunctionBegin; 700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 701 PetscValidType(mat, 1); 702 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 703 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 704 MatCheckPreallocated(mat, 1); 705 if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 706 PetscUseTypeMethod(mat, getrowuppertriangular); 707 PetscFunctionReturn(PETSC_SUCCESS); 708 } 709 710 /*@ 711 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 712 713 Not Collective 714 715 Input Parameter: 716 . mat - the matrix 717 718 Level: advanced 719 720 Note: 721 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 722 723 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 724 @*/ 725 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 726 { 727 PetscFunctionBegin; 728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 729 PetscValidType(mat, 1); 730 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 731 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 732 MatCheckPreallocated(mat, 1); 733 if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS); 734 PetscUseTypeMethod(mat, restorerowuppertriangular); 735 PetscFunctionReturn(PETSC_SUCCESS); 736 } 737 738 /*@ 739 MatSetOptionsPrefix - Sets the prefix used for searching for all 740 `Mat` options in the database. 741 742 Logically Collective 743 744 Input Parameters: 745 + A - the matrix 746 - prefix - the prefix to prepend to all option names 747 748 Level: advanced 749 750 Notes: 751 A hyphen (-) must NOT be given at the beginning of the prefix name. 752 The first character of all runtime options is AUTOMATICALLY the hyphen. 753 754 This is NOT used for options for the factorization of the matrix. Normally the 755 prefix is automatically passed in from the PC calling the factorization. To set 756 it directly use `MatSetOptionsPrefixFactor()` 757 758 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 759 @*/ 760 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 761 { 762 PetscFunctionBegin; 763 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 764 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 765 PetscFunctionReturn(PETSC_SUCCESS); 766 } 767 768 /*@ 769 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 770 for matrices created with `MatGetFactor()` 771 772 Logically Collective 773 774 Input Parameters: 775 + A - the matrix 776 - prefix - the prefix to prepend to all option names for the factored matrix 777 778 Level: developer 779 780 Notes: 781 A hyphen (-) must NOT be given at the beginning of the prefix name. 782 The first character of all runtime options is AUTOMATICALLY the hyphen. 783 784 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 785 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 786 787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 788 @*/ 789 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 790 { 791 PetscFunctionBegin; 792 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 793 if (prefix) { 794 PetscAssertPointer(prefix, 2); 795 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 796 if (prefix != A->factorprefix) { 797 PetscCall(PetscFree(A->factorprefix)); 798 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 799 } 800 } else PetscCall(PetscFree(A->factorprefix)); 801 PetscFunctionReturn(PETSC_SUCCESS); 802 } 803 804 /*@ 805 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 806 for matrices created with `MatGetFactor()` 807 808 Logically Collective 809 810 Input Parameters: 811 + A - the matrix 812 - prefix - the prefix to prepend to all option names for the factored matrix 813 814 Level: developer 815 816 Notes: 817 A hyphen (-) must NOT be given at the beginning of the prefix name. 818 The first character of all runtime options is AUTOMATICALLY the hyphen. 819 820 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 821 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 822 823 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 824 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 825 `MatSetOptionsPrefix()` 826 @*/ 827 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 828 { 829 size_t len1, len2, new_len; 830 831 PetscFunctionBegin; 832 PetscValidHeader(A, 1); 833 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 834 if (!A->factorprefix) { 835 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 836 PetscFunctionReturn(PETSC_SUCCESS); 837 } 838 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 839 840 PetscCall(PetscStrlen(A->factorprefix, &len1)); 841 PetscCall(PetscStrlen(prefix, &len2)); 842 new_len = len1 + len2 + 1; 843 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 844 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 845 PetscFunctionReturn(PETSC_SUCCESS); 846 } 847 848 /*@ 849 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 850 matrix options in the database. 851 852 Logically Collective 853 854 Input Parameters: 855 + A - the matrix 856 - prefix - the prefix to prepend to all option names 857 858 Level: advanced 859 860 Note: 861 A hyphen (-) must NOT be given at the beginning of the prefix name. 862 The first character of all runtime options is AUTOMATICALLY the hyphen. 863 864 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 865 @*/ 866 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 867 { 868 PetscFunctionBegin; 869 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 870 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 871 PetscFunctionReturn(PETSC_SUCCESS); 872 } 873 874 /*@ 875 MatGetOptionsPrefix - Gets the prefix used for searching for all 876 matrix options in the database. 877 878 Not Collective 879 880 Input Parameter: 881 . A - the matrix 882 883 Output Parameter: 884 . prefix - pointer to the prefix string used 885 886 Level: advanced 887 888 Fortran Note: 889 The user should pass in a string `prefix` of 890 sufficient length to hold the prefix. 891 892 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 893 @*/ 894 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 895 { 896 PetscFunctionBegin; 897 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 898 PetscAssertPointer(prefix, 2); 899 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 900 PetscFunctionReturn(PETSC_SUCCESS); 901 } 902 903 /*@ 904 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 905 906 Not Collective 907 908 Input Parameter: 909 . A - the matrix 910 911 Output Parameter: 912 . state - the object state 913 914 Level: advanced 915 916 Note: 917 Object state is an integer which gets increased every time 918 the object is changed. By saving and later querying the object state 919 one can determine whether information about the object is still current. 920 921 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 922 923 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 924 @*/ 925 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 929 PetscAssertPointer(state, 2); 930 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 931 PetscFunctionReturn(PETSC_SUCCESS); 932 } 933 934 /*@ 935 MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user. 936 937 Collective 938 939 Input Parameter: 940 . A - the matrix 941 942 Level: beginner 943 944 Notes: 945 The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 946 947 Users can reset the preallocation to access the original memory. 948 949 Currently only supported for `MATAIJ` matrices. 950 951 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 952 @*/ 953 PetscErrorCode MatResetPreallocation(Mat A) 954 { 955 PetscFunctionBegin; 956 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 957 PetscValidType(A, 1); 958 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 959 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 960 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 961 PetscFunctionReturn(PETSC_SUCCESS); 962 } 963 964 /*@ 965 MatSetUp - Sets up the internal matrix data structures for later use. 966 967 Collective 968 969 Input Parameter: 970 . A - the matrix 971 972 Level: intermediate 973 974 Notes: 975 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 976 setting values in the matrix. 977 978 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 979 980 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 981 @*/ 982 PetscErrorCode MatSetUp(Mat A) 983 { 984 PetscFunctionBegin; 985 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 986 if (!((PetscObject)A)->type_name) { 987 PetscMPIInt size; 988 989 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 990 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 991 } 992 if (!A->preallocated) PetscTryTypeMethod(A, setup); 993 PetscCall(PetscLayoutSetUp(A->rmap)); 994 PetscCall(PetscLayoutSetUp(A->cmap)); 995 A->preallocated = PETSC_TRUE; 996 PetscFunctionReturn(PETSC_SUCCESS); 997 } 998 999 #if defined(PETSC_HAVE_SAWS) 1000 #include <petscviewersaws.h> 1001 #endif 1002 1003 /* 1004 If threadsafety is on extraneous matrices may be printed 1005 1006 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1007 */ 1008 #if !defined(PETSC_HAVE_THREADSAFETY) 1009 static PetscInt insidematview = 0; 1010 #endif 1011 1012 /*@ 1013 MatViewFromOptions - View properties of the matrix based on options set in the options database 1014 1015 Collective 1016 1017 Input Parameters: 1018 + A - the matrix 1019 . obj - optional additional object that provides the options prefix to use 1020 - name - command line option 1021 1022 Options Database Key: 1023 . -mat_view [viewertype]:... - the viewer and its options 1024 1025 Level: intermediate 1026 1027 Note: 1028 .vb 1029 If no value is provided ascii:stdout is used 1030 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1031 for example ascii::ascii_info prints just the information about the object not all details 1032 unless :append is given filename opens in write mode, overwriting what was already there 1033 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1034 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1035 socket[:port] defaults to the standard output port 1036 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1037 .ve 1038 1039 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1040 @*/ 1041 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1042 { 1043 PetscFunctionBegin; 1044 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1045 #if !defined(PETSC_HAVE_THREADSAFETY) 1046 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1047 #endif 1048 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1049 PetscFunctionReturn(PETSC_SUCCESS); 1050 } 1051 1052 /*@ 1053 MatView - display information about a matrix in a variety ways 1054 1055 Collective on viewer 1056 1057 Input Parameters: 1058 + mat - the matrix 1059 - viewer - visualization context 1060 1061 Options Database Keys: 1062 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1063 . -mat_view ::ascii_info_detail - Prints more detailed info 1064 . -mat_view - Prints matrix in ASCII format 1065 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1066 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1067 . -display <name> - Sets display name (default is host) 1068 . -draw_pause <sec> - Sets number of seconds to pause after display 1069 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1070 . -viewer_socket_machine <machine> - - 1071 . -viewer_socket_port <port> - - 1072 . -mat_view binary - save matrix to file in binary format 1073 - -viewer_binary_filename <name> - - 1074 1075 Level: beginner 1076 1077 Notes: 1078 The available visualization contexts include 1079 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1080 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1081 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1082 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1083 1084 The user can open alternative visualization contexts with 1085 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1086 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1087 specified file; corresponding input uses `MatLoad()` 1088 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1089 an X window display 1090 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1091 Currently only the `MATSEQDENSE` and `MATAIJ` 1092 matrix types support the Socket viewer. 1093 1094 The user can call `PetscViewerPushFormat()` to specify the output 1095 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1096 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1097 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1098 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1099 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1100 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1101 format common among all matrix types 1102 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1103 format (which is in many cases the same as the default) 1104 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1105 size and structure (not the matrix entries) 1106 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1107 the matrix structure (still not vector or matrix entries) 1108 1109 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1110 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1111 1112 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1113 1114 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1115 viewer is used. 1116 1117 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1118 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1119 1120 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1121 and then use the following mouse functions. 1122 .vb 1123 left mouse: zoom in 1124 middle mouse: zoom out 1125 right mouse: continue with the simulation 1126 .ve 1127 1128 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1129 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1130 @*/ 1131 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1132 { 1133 PetscInt rows, cols, rbs, cbs; 1134 PetscBool isascii, isstring, issaws; 1135 PetscViewerFormat format; 1136 PetscMPIInt size; 1137 1138 PetscFunctionBegin; 1139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1140 PetscValidType(mat, 1); 1141 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1142 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1143 1144 PetscCall(PetscViewerGetFormat(viewer, &format)); 1145 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1146 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1147 1148 #if !defined(PETSC_HAVE_THREADSAFETY) 1149 insidematview++; 1150 #endif 1151 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1152 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1153 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1154 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"); 1155 1156 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1157 if (isascii) { 1158 if (!mat->preallocated) { 1159 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1160 #if !defined(PETSC_HAVE_THREADSAFETY) 1161 insidematview--; 1162 #endif 1163 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1164 PetscFunctionReturn(PETSC_SUCCESS); 1165 } 1166 if (!mat->assembled) { 1167 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1168 #if !defined(PETSC_HAVE_THREADSAFETY) 1169 insidematview--; 1170 #endif 1171 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1172 PetscFunctionReturn(PETSC_SUCCESS); 1173 } 1174 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1175 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1176 MatNullSpace nullsp, transnullsp; 1177 1178 PetscCall(PetscViewerASCIIPushTab(viewer)); 1179 PetscCall(MatGetSize(mat, &rows, &cols)); 1180 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1181 if (rbs != 1 || cbs != 1) { 1182 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" : "")); 1183 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1184 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1185 if (mat->factortype) { 1186 MatSolverType solver; 1187 PetscCall(MatFactorGetSolverType(mat, &solver)); 1188 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1189 } 1190 if (mat->ops->getinfo) { 1191 MatInfo info; 1192 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1193 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1194 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1195 } 1196 PetscCall(MatGetNullSpace(mat, &nullsp)); 1197 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1198 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1199 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1200 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1201 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1202 PetscCall(PetscViewerASCIIPushTab(viewer)); 1203 PetscCall(MatProductView(mat, viewer)); 1204 PetscCall(PetscViewerASCIIPopTab(viewer)); 1205 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1206 IS tmp; 1207 1208 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1209 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1210 PetscCall(PetscViewerASCIIPushTab(viewer)); 1211 PetscCall(ISView(tmp, viewer)); 1212 PetscCall(PetscViewerASCIIPopTab(viewer)); 1213 PetscCall(ISDestroy(&tmp)); 1214 } 1215 } 1216 } else if (issaws) { 1217 #if defined(PETSC_HAVE_SAWS) 1218 PetscMPIInt rank; 1219 1220 PetscCall(PetscObjectName((PetscObject)mat)); 1221 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1222 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1223 #endif 1224 } else if (isstring) { 1225 const char *type; 1226 PetscCall(MatGetType(mat, &type)); 1227 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1228 PetscTryTypeMethod(mat, view, viewer); 1229 } 1230 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1231 PetscCall(PetscViewerASCIIPushTab(viewer)); 1232 PetscUseTypeMethod(mat, viewnative, viewer); 1233 PetscCall(PetscViewerASCIIPopTab(viewer)); 1234 } else if (mat->ops->view) { 1235 PetscCall(PetscViewerASCIIPushTab(viewer)); 1236 PetscUseTypeMethod(mat, view, viewer); 1237 PetscCall(PetscViewerASCIIPopTab(viewer)); 1238 } 1239 if (isascii) { 1240 PetscCall(PetscViewerGetFormat(viewer, &format)); 1241 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1242 } 1243 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1244 #if !defined(PETSC_HAVE_THREADSAFETY) 1245 insidematview--; 1246 #endif 1247 PetscFunctionReturn(PETSC_SUCCESS); 1248 } 1249 1250 #if defined(PETSC_USE_DEBUG) 1251 #include <../src/sys/totalview/tv_data_display.h> 1252 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1253 { 1254 TV_add_row("Local rows", "int", &mat->rmap->n); 1255 TV_add_row("Local columns", "int", &mat->cmap->n); 1256 TV_add_row("Global rows", "int", &mat->rmap->N); 1257 TV_add_row("Global columns", "int", &mat->cmap->N); 1258 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1259 return TV_format_OK; 1260 } 1261 #endif 1262 1263 /*@ 1264 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1265 with `MatView()`. The matrix format is determined from the options database. 1266 Generates a parallel MPI matrix if the communicator has more than one 1267 processor. The default matrix type is `MATAIJ`. 1268 1269 Collective 1270 1271 Input Parameters: 1272 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1273 or some related function before a call to `MatLoad()` 1274 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1275 1276 Options Database Key: 1277 . -matload_block_size <bs> - set block size 1278 1279 Level: beginner 1280 1281 Notes: 1282 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1283 `Mat` before calling this routine if you wish to set it from the options database. 1284 1285 `MatLoad()` automatically loads into the options database any options 1286 given in the file filename.info where filename is the name of the file 1287 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1288 file will be ignored if you use the -viewer_binary_skip_info option. 1289 1290 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1291 sets the default matrix type AIJ and sets the local and global sizes. 1292 If type and/or size is already set, then the same are used. 1293 1294 In parallel, each processor can load a subset of rows (or the 1295 entire matrix). This routine is especially useful when a large 1296 matrix is stored on disk and only part of it is desired on each 1297 processor. For example, a parallel solver may access only some of 1298 the rows from each processor. The algorithm used here reads 1299 relatively small blocks of data rather than reading the entire 1300 matrix and then subsetting it. 1301 1302 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1303 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1304 or the sequence like 1305 .vb 1306 `PetscViewer` v; 1307 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1308 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1309 `PetscViewerSetFromOptions`(v); 1310 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1311 `PetscViewerFileSetName`(v,"datafile"); 1312 .ve 1313 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1314 $ -viewer_type {binary, hdf5} 1315 1316 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1317 and src/mat/tutorials/ex10.c with the second approach. 1318 1319 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1320 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1321 Multiple objects, both matrices and vectors, can be stored within the same file. 1322 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1323 1324 Most users should not need to know the details of the binary storage 1325 format, since `MatLoad()` and `MatView()` completely hide these details. 1326 But for anyone who is interested, the standard binary matrix storage 1327 format is 1328 1329 .vb 1330 PetscInt MAT_FILE_CLASSID 1331 PetscInt number of rows 1332 PetscInt number of columns 1333 PetscInt total number of nonzeros 1334 PetscInt *number nonzeros in each row 1335 PetscInt *column indices of all nonzeros (starting index is zero) 1336 PetscScalar *values of all nonzeros 1337 .ve 1338 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1339 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 1340 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1341 1342 PETSc automatically does the byte swapping for 1343 machines that store the bytes reversed. Thus if you write your own binary 1344 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1345 and `PetscBinaryWrite()` to see how this may be done. 1346 1347 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1348 Each processor's chunk is loaded independently by its owning MPI process. 1349 Multiple objects, both matrices and vectors, can be stored within the same file. 1350 They are looked up by their PetscObject name. 1351 1352 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1353 by default the same structure and naming of the AIJ arrays and column count 1354 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1355 $ save example.mat A b -v7.3 1356 can be directly read by this routine (see Reference 1 for details). 1357 1358 Depending on your MATLAB version, this format might be a default, 1359 otherwise you can set it as default in Preferences. 1360 1361 Unless -nocompression flag is used to save the file in MATLAB, 1362 PETSc must be configured with ZLIB package. 1363 1364 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1365 1366 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1367 1368 Corresponding `MatView()` is not yet implemented. 1369 1370 The loaded matrix is actually a transpose of the original one in MATLAB, 1371 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1372 With this format, matrix is automatically transposed by PETSc, 1373 unless the matrix is marked as SPD or symmetric 1374 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1375 1376 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1377 1378 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1379 @*/ 1380 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1381 { 1382 PetscBool flg; 1383 1384 PetscFunctionBegin; 1385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1386 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1387 1388 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1389 1390 flg = PETSC_FALSE; 1391 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1392 if (flg) { 1393 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1394 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1395 } 1396 flg = PETSC_FALSE; 1397 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1398 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1399 1400 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1401 PetscUseTypeMethod(mat, load, viewer); 1402 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1403 PetscFunctionReturn(PETSC_SUCCESS); 1404 } 1405 1406 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1407 { 1408 Mat_Redundant *redund = *redundant; 1409 1410 PetscFunctionBegin; 1411 if (redund) { 1412 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1413 PetscCall(ISDestroy(&redund->isrow)); 1414 PetscCall(ISDestroy(&redund->iscol)); 1415 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1416 } else { 1417 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1418 PetscCall(PetscFree(redund->sbuf_j)); 1419 PetscCall(PetscFree(redund->sbuf_a)); 1420 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1421 PetscCall(PetscFree(redund->rbuf_j[i])); 1422 PetscCall(PetscFree(redund->rbuf_a[i])); 1423 } 1424 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1425 } 1426 1427 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1428 PetscCall(PetscFree(redund)); 1429 } 1430 PetscFunctionReturn(PETSC_SUCCESS); 1431 } 1432 1433 /*@ 1434 MatDestroy - Frees space taken by a matrix. 1435 1436 Collective 1437 1438 Input Parameter: 1439 . A - the matrix 1440 1441 Level: beginner 1442 1443 Developer Note: 1444 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1445 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1446 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1447 if changes are needed here. 1448 1449 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1450 @*/ 1451 PetscErrorCode MatDestroy(Mat *A) 1452 { 1453 PetscFunctionBegin; 1454 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1455 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1456 if (--((PetscObject)*A)->refct > 0) { 1457 *A = NULL; 1458 PetscFunctionReturn(PETSC_SUCCESS); 1459 } 1460 1461 /* if memory was published with SAWs then destroy it */ 1462 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1463 PetscTryTypeMethod(*A, destroy); 1464 1465 PetscCall(PetscFree((*A)->factorprefix)); 1466 PetscCall(PetscFree((*A)->defaultvectype)); 1467 PetscCall(PetscFree((*A)->defaultrandtype)); 1468 PetscCall(PetscFree((*A)->bsizes)); 1469 PetscCall(PetscFree((*A)->solvertype)); 1470 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1471 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1472 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1473 PetscCall(MatProductClear(*A)); 1474 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1475 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1476 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1477 PetscCall(MatDestroy(&(*A)->schur)); 1478 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1479 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1480 PetscCall(PetscHeaderDestroy(A)); 1481 PetscFunctionReturn(PETSC_SUCCESS); 1482 } 1483 1484 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1485 /*@ 1486 MatSetValues - Inserts or adds a block of values into a matrix. 1487 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1488 MUST be called after all calls to `MatSetValues()` have been completed. 1489 1490 Not Collective 1491 1492 Input Parameters: 1493 + mat - the matrix 1494 . v - a logically two-dimensional array of values 1495 . m - the number of rows 1496 . idxm - the global indices of the rows 1497 . n - the number of columns 1498 . idxn - the global indices of the columns 1499 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1500 1501 Level: beginner 1502 1503 Notes: 1504 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1505 1506 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1507 options cannot be mixed without intervening calls to the assembly 1508 routines. 1509 1510 `MatSetValues()` uses 0-based row and column numbers in Fortran 1511 as well as in C. 1512 1513 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1514 simply ignored. This allows easily inserting element stiffness matrices 1515 with homogeneous Dirichlet boundary conditions that you don't want represented 1516 in the matrix. 1517 1518 Efficiency Alert: 1519 The routine `MatSetValuesBlocked()` may offer much better efficiency 1520 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1521 1522 Fortran Notes: 1523 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1524 .vb 1525 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1526 .ve 1527 1528 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1529 1530 Developer Note: 1531 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1532 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1533 1534 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1535 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1536 @*/ 1537 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1538 { 1539 PetscFunctionBeginHot; 1540 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1541 PetscValidType(mat, 1); 1542 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1543 PetscAssertPointer(idxm, 3); 1544 PetscAssertPointer(idxn, 5); 1545 MatCheckPreallocated(mat, 1); 1546 1547 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1548 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1549 1550 if (PetscDefined(USE_DEBUG)) { 1551 PetscInt i, j; 1552 1553 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1554 if (v) { 1555 for (i = 0; i < m; i++) { 1556 for (j = 0; j < n; j++) { 1557 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1558 #if defined(PETSC_USE_COMPLEX) 1559 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]); 1560 #else 1561 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]); 1562 #endif 1563 } 1564 } 1565 } 1566 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); 1567 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); 1568 } 1569 1570 if (mat->assembled) { 1571 mat->was_assembled = PETSC_TRUE; 1572 mat->assembled = PETSC_FALSE; 1573 } 1574 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1575 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1576 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1577 PetscFunctionReturn(PETSC_SUCCESS); 1578 } 1579 1580 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1581 /*@ 1582 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1583 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1584 MUST be called after all calls to `MatSetValues()` have been completed. 1585 1586 Not Collective 1587 1588 Input Parameters: 1589 + mat - the matrix 1590 . v - a logically two-dimensional array of values 1591 . ism - the rows to provide 1592 . isn - the columns to provide 1593 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1594 1595 Level: beginner 1596 1597 Notes: 1598 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1599 1600 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1601 options cannot be mixed without intervening calls to the assembly 1602 routines. 1603 1604 `MatSetValues()` uses 0-based row and column numbers in Fortran 1605 as well as in C. 1606 1607 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1608 simply ignored. This allows easily inserting element stiffness matrices 1609 with homogeneous Dirichlet boundary conditions that you don't want represented 1610 in the matrix. 1611 1612 Efficiency Alert: 1613 The routine `MatSetValuesBlocked()` may offer much better efficiency 1614 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1615 1616 This is currently not optimized for any particular `ISType` 1617 1618 Developer Note: 1619 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1620 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1621 1622 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1623 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1624 @*/ 1625 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1626 { 1627 PetscInt m, n; 1628 const PetscInt *rows, *cols; 1629 1630 PetscFunctionBeginHot; 1631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1632 PetscCall(ISGetIndices(ism, &rows)); 1633 PetscCall(ISGetIndices(isn, &cols)); 1634 PetscCall(ISGetLocalSize(ism, &m)); 1635 PetscCall(ISGetLocalSize(isn, &n)); 1636 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1637 PetscCall(ISRestoreIndices(ism, &rows)); 1638 PetscCall(ISRestoreIndices(isn, &cols)); 1639 PetscFunctionReturn(PETSC_SUCCESS); 1640 } 1641 1642 /*@ 1643 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1644 values into a matrix 1645 1646 Not Collective 1647 1648 Input Parameters: 1649 + mat - the matrix 1650 . row - the (block) row to set 1651 - v - a logically two-dimensional array of values 1652 1653 Level: intermediate 1654 1655 Notes: 1656 The values, `v`, are column-oriented (for the block version) and sorted 1657 1658 All the nonzero values in `row` must be provided 1659 1660 The matrix must have previously had its column indices set, likely by having been assembled. 1661 1662 `row` must belong to this MPI process 1663 1664 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1665 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1666 @*/ 1667 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1668 { 1669 PetscInt globalrow; 1670 1671 PetscFunctionBegin; 1672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1673 PetscValidType(mat, 1); 1674 PetscAssertPointer(v, 3); 1675 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1676 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1677 PetscFunctionReturn(PETSC_SUCCESS); 1678 } 1679 1680 /*@ 1681 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1682 values into a matrix 1683 1684 Not Collective 1685 1686 Input Parameters: 1687 + mat - the matrix 1688 . row - the (block) row to set 1689 - 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 1690 1691 Level: advanced 1692 1693 Notes: 1694 The values, `v`, are column-oriented for the block version. 1695 1696 All the nonzeros in `row` must be provided 1697 1698 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1699 1700 `row` must belong to this process 1701 1702 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1703 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1704 @*/ 1705 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1706 { 1707 PetscFunctionBeginHot; 1708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1709 PetscValidType(mat, 1); 1710 MatCheckPreallocated(mat, 1); 1711 PetscAssertPointer(v, 3); 1712 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1713 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1714 mat->insertmode = INSERT_VALUES; 1715 1716 if (mat->assembled) { 1717 mat->was_assembled = PETSC_TRUE; 1718 mat->assembled = PETSC_FALSE; 1719 } 1720 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1721 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1722 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1723 PetscFunctionReturn(PETSC_SUCCESS); 1724 } 1725 1726 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1727 /*@ 1728 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1729 Using structured grid indexing 1730 1731 Not Collective 1732 1733 Input Parameters: 1734 + mat - the matrix 1735 . m - number of rows being entered 1736 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1737 . n - number of columns being entered 1738 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1739 . v - a logically two-dimensional array of values 1740 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1741 1742 Level: beginner 1743 1744 Notes: 1745 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1746 1747 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1748 options cannot be mixed without intervening calls to the assembly 1749 routines. 1750 1751 The grid coordinates are across the entire grid, not just the local portion 1752 1753 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1754 as well as in C. 1755 1756 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1757 1758 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1759 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1760 1761 The columns and rows in the stencil passed in MUST be contained within the 1762 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1763 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1764 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1765 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1766 1767 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1768 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1769 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1770 `DM_BOUNDARY_PERIODIC` boundary type. 1771 1772 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 1773 a single value per point) you can skip filling those indices. 1774 1775 Inspired by the structured grid interface to the HYPRE package 1776 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1777 1778 Efficiency Alert: 1779 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1780 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1781 1782 Fortran Note: 1783 `idxm` and `idxn` should be declared as 1784 $ MatStencil idxm(4,m),idxn(4,n) 1785 and the values inserted using 1786 .vb 1787 idxm(MatStencil_i,1) = i 1788 idxm(MatStencil_j,1) = j 1789 idxm(MatStencil_k,1) = k 1790 idxm(MatStencil_c,1) = c 1791 etc 1792 .ve 1793 1794 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1795 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1796 @*/ 1797 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1798 { 1799 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1800 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1801 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1802 1803 PetscFunctionBegin; 1804 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1805 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1806 PetscValidType(mat, 1); 1807 PetscAssertPointer(idxm, 3); 1808 PetscAssertPointer(idxn, 5); 1809 1810 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1811 jdxm = buf; 1812 jdxn = buf + m; 1813 } else { 1814 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1815 jdxm = bufm; 1816 jdxn = bufn; 1817 } 1818 for (i = 0; i < m; i++) { 1819 for (j = 0; j < 3 - sdim; j++) dxm++; 1820 tmp = *dxm++ - starts[0]; 1821 for (j = 0; j < dim - 1; j++) { 1822 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1823 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1824 } 1825 if (mat->stencil.noc) dxm++; 1826 jdxm[i] = tmp; 1827 } 1828 for (i = 0; i < n; i++) { 1829 for (j = 0; j < 3 - sdim; j++) dxn++; 1830 tmp = *dxn++ - starts[0]; 1831 for (j = 0; j < dim - 1; j++) { 1832 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1833 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1834 } 1835 if (mat->stencil.noc) dxn++; 1836 jdxn[i] = tmp; 1837 } 1838 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1839 PetscCall(PetscFree2(bufm, bufn)); 1840 PetscFunctionReturn(PETSC_SUCCESS); 1841 } 1842 1843 /*@ 1844 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1845 Using structured grid indexing 1846 1847 Not Collective 1848 1849 Input Parameters: 1850 + mat - the matrix 1851 . m - number of rows being entered 1852 . idxm - grid coordinates for matrix rows being entered 1853 . n - number of columns being entered 1854 . idxn - grid coordinates for matrix columns being entered 1855 . v - a logically two-dimensional array of values 1856 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1857 1858 Level: beginner 1859 1860 Notes: 1861 By default the values, `v`, are row-oriented and unsorted. 1862 See `MatSetOption()` for other options. 1863 1864 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1865 options cannot be mixed without intervening calls to the assembly 1866 routines. 1867 1868 The grid coordinates are across the entire grid, not just the local portion 1869 1870 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1871 as well as in C. 1872 1873 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1874 1875 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1876 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1877 1878 The columns and rows in the stencil passed in MUST be contained within the 1879 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1880 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1881 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1882 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1883 1884 Negative indices may be passed in idxm and idxn, these rows and columns are 1885 simply ignored. This allows easily inserting element stiffness matrices 1886 with homogeneous Dirichlet boundary conditions that you don't want represented 1887 in the matrix. 1888 1889 Inspired by the structured grid interface to the HYPRE package 1890 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1891 1892 Fortran Note: 1893 `idxm` and `idxn` should be declared as 1894 $ MatStencil idxm(4,m),idxn(4,n) 1895 and the values inserted using 1896 .vb 1897 idxm(MatStencil_i,1) = i 1898 idxm(MatStencil_j,1) = j 1899 idxm(MatStencil_k,1) = k 1900 etc 1901 .ve 1902 1903 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1904 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1905 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1906 @*/ 1907 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1908 { 1909 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1910 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1911 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1912 1913 PetscFunctionBegin; 1914 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1915 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1916 PetscValidType(mat, 1); 1917 PetscAssertPointer(idxm, 3); 1918 PetscAssertPointer(idxn, 5); 1919 PetscAssertPointer(v, 6); 1920 1921 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1922 jdxm = buf; 1923 jdxn = buf + m; 1924 } else { 1925 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1926 jdxm = bufm; 1927 jdxn = bufn; 1928 } 1929 for (i = 0; i < m; i++) { 1930 for (j = 0; j < 3 - sdim; j++) dxm++; 1931 tmp = *dxm++ - starts[0]; 1932 for (j = 0; j < sdim - 1; j++) { 1933 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1934 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1935 } 1936 dxm++; 1937 jdxm[i] = tmp; 1938 } 1939 for (i = 0; i < n; i++) { 1940 for (j = 0; j < 3 - sdim; j++) dxn++; 1941 tmp = *dxn++ - starts[0]; 1942 for (j = 0; j < sdim - 1; j++) { 1943 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1944 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1945 } 1946 dxn++; 1947 jdxn[i] = tmp; 1948 } 1949 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1950 PetscCall(PetscFree2(bufm, bufn)); 1951 PetscFunctionReturn(PETSC_SUCCESS); 1952 } 1953 1954 /*@ 1955 MatSetStencil - Sets the grid information for setting values into a matrix via 1956 `MatSetValuesStencil()` 1957 1958 Not Collective 1959 1960 Input Parameters: 1961 + mat - the matrix 1962 . dim - dimension of the grid 1, 2, or 3 1963 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1964 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1965 - dof - number of degrees of freedom per node 1966 1967 Level: beginner 1968 1969 Notes: 1970 Inspired by the structured grid interface to the HYPRE package 1971 (www.llnl.gov/CASC/hyper) 1972 1973 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1974 user. 1975 1976 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1977 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1978 @*/ 1979 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1980 { 1981 PetscFunctionBegin; 1982 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1983 PetscAssertPointer(dims, 3); 1984 PetscAssertPointer(starts, 4); 1985 1986 mat->stencil.dim = dim + (dof > 1); 1987 for (PetscInt i = 0; i < dim; i++) { 1988 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1989 mat->stencil.starts[i] = starts[dim - i - 1]; 1990 } 1991 mat->stencil.dims[dim] = dof; 1992 mat->stencil.starts[dim] = 0; 1993 mat->stencil.noc = (PetscBool)(dof == 1); 1994 PetscFunctionReturn(PETSC_SUCCESS); 1995 } 1996 1997 /*@ 1998 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1999 2000 Not Collective 2001 2002 Input Parameters: 2003 + mat - the matrix 2004 . v - a logically two-dimensional array of values 2005 . m - the number of block rows 2006 . idxm - the global block indices 2007 . n - the number of block columns 2008 . idxn - the global block indices 2009 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2010 2011 Level: intermediate 2012 2013 Notes: 2014 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2015 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2016 2017 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2018 NOT the total number of rows/columns; for example, if the block size is 2 and 2019 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2020 The values in `idxm` would be 1 2; that is the first index for each block divided by 2021 the block size. 2022 2023 You must call `MatSetBlockSize()` when constructing this matrix (before 2024 preallocating it). 2025 2026 By default the values, `v`, are row-oriented, so the layout of 2027 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2028 2029 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2030 options cannot be mixed without intervening calls to the assembly 2031 routines. 2032 2033 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2034 as well as in C. 2035 2036 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2037 simply ignored. This allows easily inserting element stiffness matrices 2038 with homogeneous Dirichlet boundary conditions that you don't want represented 2039 in the matrix. 2040 2041 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2042 internal searching must be done to determine where to place the 2043 data in the matrix storage space. By instead inserting blocks of 2044 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2045 reduced. 2046 2047 Example: 2048 .vb 2049 Suppose m=n=2 and block size(bs) = 2 The array is 2050 2051 1 2 | 3 4 2052 5 6 | 7 8 2053 - - - | - - - 2054 9 10 | 11 12 2055 13 14 | 15 16 2056 2057 v[] should be passed in like 2058 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2059 2060 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2061 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2062 .ve 2063 2064 Fortran Notes: 2065 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2066 .vb 2067 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2068 .ve 2069 2070 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2071 2072 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2073 @*/ 2074 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2075 { 2076 PetscFunctionBeginHot; 2077 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2078 PetscValidType(mat, 1); 2079 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2080 PetscAssertPointer(idxm, 3); 2081 PetscAssertPointer(idxn, 5); 2082 MatCheckPreallocated(mat, 1); 2083 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2084 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2085 if (PetscDefined(USE_DEBUG)) { 2086 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2087 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2088 } 2089 if (PetscDefined(USE_DEBUG)) { 2090 PetscInt rbs, cbs, M, N, i; 2091 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2092 PetscCall(MatGetSize(mat, &M, &N)); 2093 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); 2094 for (i = 0; i < n; i++) 2095 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); 2096 } 2097 if (mat->assembled) { 2098 mat->was_assembled = PETSC_TRUE; 2099 mat->assembled = PETSC_FALSE; 2100 } 2101 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2102 if (mat->ops->setvaluesblocked) { 2103 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2104 } else { 2105 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2106 PetscInt i, j, bs, cbs; 2107 2108 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2109 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2110 iidxm = buf; 2111 iidxn = buf + m * bs; 2112 } else { 2113 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2114 iidxm = bufr; 2115 iidxn = bufc; 2116 } 2117 for (i = 0; i < m; i++) { 2118 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2119 } 2120 if (m != n || bs != cbs || idxm != idxn) { 2121 for (i = 0; i < n; i++) { 2122 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2123 } 2124 } else iidxn = iidxm; 2125 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2126 PetscCall(PetscFree2(bufr, bufc)); 2127 } 2128 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2129 PetscFunctionReturn(PETSC_SUCCESS); 2130 } 2131 2132 /*@ 2133 MatGetValues - Gets a block of local values from a matrix. 2134 2135 Not Collective; can only return values that are owned by the give process 2136 2137 Input Parameters: 2138 + mat - the matrix 2139 . v - a logically two-dimensional array for storing the values 2140 . m - the number of rows 2141 . idxm - the global indices of the rows 2142 . n - the number of columns 2143 - idxn - the global indices of the columns 2144 2145 Level: advanced 2146 2147 Notes: 2148 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2149 The values, `v`, are then returned in a row-oriented format, 2150 analogous to that used by default in `MatSetValues()`. 2151 2152 `MatGetValues()` uses 0-based row and column numbers in 2153 Fortran as well as in C. 2154 2155 `MatGetValues()` requires that the matrix has been assembled 2156 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2157 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2158 without intermediate matrix assembly. 2159 2160 Negative row or column indices will be ignored and those locations in `v` will be 2161 left unchanged. 2162 2163 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2164 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2165 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2166 2167 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2168 @*/ 2169 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2170 { 2171 PetscFunctionBegin; 2172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2173 PetscValidType(mat, 1); 2174 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2175 PetscAssertPointer(idxm, 3); 2176 PetscAssertPointer(idxn, 5); 2177 PetscAssertPointer(v, 6); 2178 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2179 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2180 MatCheckPreallocated(mat, 1); 2181 2182 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2183 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2184 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2185 PetscFunctionReturn(PETSC_SUCCESS); 2186 } 2187 2188 /*@ 2189 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2190 defined previously by `MatSetLocalToGlobalMapping()` 2191 2192 Not Collective 2193 2194 Input Parameters: 2195 + mat - the matrix 2196 . nrow - number of rows 2197 . irow - the row local indices 2198 . ncol - number of columns 2199 - icol - the column local indices 2200 2201 Output Parameter: 2202 . y - a logically two-dimensional array of values 2203 2204 Level: advanced 2205 2206 Notes: 2207 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2208 2209 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, 2210 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2211 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2212 with `MatSetLocalToGlobalMapping()`. 2213 2214 Developer Note: 2215 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2216 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2217 2218 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2219 `MatSetValuesLocal()`, `MatGetValues()` 2220 @*/ 2221 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2222 { 2223 PetscFunctionBeginHot; 2224 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2225 PetscValidType(mat, 1); 2226 MatCheckPreallocated(mat, 1); 2227 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2228 PetscAssertPointer(irow, 3); 2229 PetscAssertPointer(icol, 5); 2230 if (PetscDefined(USE_DEBUG)) { 2231 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2232 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2233 } 2234 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2235 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2236 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2237 else { 2238 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2239 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2240 irowm = buf; 2241 icolm = buf + nrow; 2242 } else { 2243 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2244 irowm = bufr; 2245 icolm = bufc; 2246 } 2247 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2248 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2249 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2250 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2251 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2252 PetscCall(PetscFree2(bufr, bufc)); 2253 } 2254 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2255 PetscFunctionReturn(PETSC_SUCCESS); 2256 } 2257 2258 /*@ 2259 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2260 the same size. Currently, this can only be called once and creates the given matrix. 2261 2262 Not Collective 2263 2264 Input Parameters: 2265 + mat - the matrix 2266 . nb - the number of blocks 2267 . bs - the number of rows (and columns) in each block 2268 . rows - a concatenation of the rows for each block 2269 - v - a concatenation of logically two-dimensional arrays of values 2270 2271 Level: advanced 2272 2273 Notes: 2274 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2275 2276 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2277 2278 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2279 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2280 @*/ 2281 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2282 { 2283 PetscFunctionBegin; 2284 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2285 PetscValidType(mat, 1); 2286 PetscAssertPointer(rows, 4); 2287 PetscAssertPointer(v, 5); 2288 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2289 2290 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2291 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2292 else { 2293 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2294 } 2295 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2296 PetscFunctionReturn(PETSC_SUCCESS); 2297 } 2298 2299 /*@ 2300 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2301 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2302 using a local (per-processor) numbering. 2303 2304 Not Collective 2305 2306 Input Parameters: 2307 + x - the matrix 2308 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2309 - cmapping - column mapping 2310 2311 Level: intermediate 2312 2313 Note: 2314 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2315 2316 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2317 @*/ 2318 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2319 { 2320 PetscFunctionBegin; 2321 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2322 PetscValidType(x, 1); 2323 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2324 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2325 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2326 else { 2327 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2328 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2329 } 2330 PetscFunctionReturn(PETSC_SUCCESS); 2331 } 2332 2333 /*@ 2334 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2335 2336 Not Collective 2337 2338 Input Parameter: 2339 . A - the matrix 2340 2341 Output Parameters: 2342 + rmapping - row mapping 2343 - cmapping - column mapping 2344 2345 Level: advanced 2346 2347 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2348 @*/ 2349 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2350 { 2351 PetscFunctionBegin; 2352 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2353 PetscValidType(A, 1); 2354 if (rmapping) { 2355 PetscAssertPointer(rmapping, 2); 2356 *rmapping = A->rmap->mapping; 2357 } 2358 if (cmapping) { 2359 PetscAssertPointer(cmapping, 3); 2360 *cmapping = A->cmap->mapping; 2361 } 2362 PetscFunctionReturn(PETSC_SUCCESS); 2363 } 2364 2365 /*@ 2366 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2367 2368 Logically Collective 2369 2370 Input Parameters: 2371 + A - the matrix 2372 . rmap - row layout 2373 - cmap - column layout 2374 2375 Level: advanced 2376 2377 Note: 2378 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2379 2380 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2381 @*/ 2382 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2383 { 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2386 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2387 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2388 PetscFunctionReturn(PETSC_SUCCESS); 2389 } 2390 2391 /*@ 2392 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2393 2394 Not Collective 2395 2396 Input Parameter: 2397 . A - the matrix 2398 2399 Output Parameters: 2400 + rmap - row layout 2401 - cmap - column layout 2402 2403 Level: advanced 2404 2405 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2406 @*/ 2407 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2408 { 2409 PetscFunctionBegin; 2410 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2411 PetscValidType(A, 1); 2412 if (rmap) { 2413 PetscAssertPointer(rmap, 2); 2414 *rmap = A->rmap; 2415 } 2416 if (cmap) { 2417 PetscAssertPointer(cmap, 3); 2418 *cmap = A->cmap; 2419 } 2420 PetscFunctionReturn(PETSC_SUCCESS); 2421 } 2422 2423 /*@ 2424 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2425 using a local numbering of the rows and columns. 2426 2427 Not Collective 2428 2429 Input Parameters: 2430 + mat - the matrix 2431 . nrow - number of rows 2432 . irow - the row local indices 2433 . ncol - number of columns 2434 . icol - the column local indices 2435 . y - a logically two-dimensional array of values 2436 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2437 2438 Level: intermediate 2439 2440 Notes: 2441 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2442 2443 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2444 options cannot be mixed without intervening calls to the assembly 2445 routines. 2446 2447 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2448 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2449 2450 Fortran Notes: 2451 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2452 .vb 2453 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2454 .ve 2455 2456 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2457 2458 Developer Note: 2459 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2460 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2461 2462 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2463 `MatGetValuesLocal()` 2464 @*/ 2465 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2466 { 2467 PetscFunctionBeginHot; 2468 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2469 PetscValidType(mat, 1); 2470 MatCheckPreallocated(mat, 1); 2471 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2472 PetscAssertPointer(irow, 3); 2473 PetscAssertPointer(icol, 5); 2474 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2475 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2476 if (PetscDefined(USE_DEBUG)) { 2477 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2478 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2479 } 2480 2481 if (mat->assembled) { 2482 mat->was_assembled = PETSC_TRUE; 2483 mat->assembled = PETSC_FALSE; 2484 } 2485 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2486 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2487 else { 2488 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2489 const PetscInt *irowm, *icolm; 2490 2491 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2492 bufr = buf; 2493 bufc = buf + nrow; 2494 irowm = bufr; 2495 icolm = bufc; 2496 } else { 2497 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2498 irowm = bufr; 2499 icolm = bufc; 2500 } 2501 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2502 else irowm = irow; 2503 if (mat->cmap->mapping) { 2504 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2505 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2506 } else icolm = irowm; 2507 } else icolm = icol; 2508 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2509 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2510 } 2511 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2512 PetscFunctionReturn(PETSC_SUCCESS); 2513 } 2514 2515 /*@ 2516 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2517 using a local ordering of the nodes a block at a time. 2518 2519 Not Collective 2520 2521 Input Parameters: 2522 + mat - the matrix 2523 . nrow - number of rows 2524 . irow - the row local indices 2525 . ncol - number of columns 2526 . icol - the column local indices 2527 . y - a logically two-dimensional array of values 2528 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2529 2530 Level: intermediate 2531 2532 Notes: 2533 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2534 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2535 2536 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2537 options cannot be mixed without intervening calls to the assembly 2538 routines. 2539 2540 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2541 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2542 2543 Fortran Notes: 2544 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2545 .vb 2546 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2547 .ve 2548 2549 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2550 2551 Developer Note: 2552 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2553 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2554 2555 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2556 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2557 @*/ 2558 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2559 { 2560 PetscFunctionBeginHot; 2561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2562 PetscValidType(mat, 1); 2563 MatCheckPreallocated(mat, 1); 2564 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2565 PetscAssertPointer(irow, 3); 2566 PetscAssertPointer(icol, 5); 2567 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2568 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2569 if (PetscDefined(USE_DEBUG)) { 2570 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2571 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); 2572 } 2573 2574 if (mat->assembled) { 2575 mat->was_assembled = PETSC_TRUE; 2576 mat->assembled = PETSC_FALSE; 2577 } 2578 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2579 PetscInt irbs, rbs; 2580 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2581 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2582 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2583 } 2584 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2585 PetscInt icbs, cbs; 2586 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2587 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2588 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2589 } 2590 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2591 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2592 else { 2593 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2594 const PetscInt *irowm, *icolm; 2595 2596 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2597 bufr = buf; 2598 bufc = buf + nrow; 2599 irowm = bufr; 2600 icolm = bufc; 2601 } else { 2602 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2603 irowm = bufr; 2604 icolm = bufc; 2605 } 2606 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2607 else irowm = irow; 2608 if (mat->cmap->mapping) { 2609 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2610 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2611 } else icolm = irowm; 2612 } else icolm = icol; 2613 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2614 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2615 } 2616 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2617 PetscFunctionReturn(PETSC_SUCCESS); 2618 } 2619 2620 /*@ 2621 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2622 2623 Collective 2624 2625 Input Parameters: 2626 + mat - the matrix 2627 - x - the vector to be multiplied 2628 2629 Output Parameter: 2630 . y - the result 2631 2632 Level: developer 2633 2634 Note: 2635 The vectors `x` and `y` cannot be the same. I.e., one cannot 2636 call `MatMultDiagonalBlock`(A,y,y). 2637 2638 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2639 @*/ 2640 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2641 { 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2644 PetscValidType(mat, 1); 2645 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2646 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2647 2648 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2649 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2650 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2651 MatCheckPreallocated(mat, 1); 2652 2653 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2654 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2655 PetscFunctionReturn(PETSC_SUCCESS); 2656 } 2657 2658 /*@ 2659 MatMult - Computes the matrix-vector product, $y = Ax$. 2660 2661 Neighbor-wise Collective 2662 2663 Input Parameters: 2664 + mat - the matrix 2665 - x - the vector to be multiplied 2666 2667 Output Parameter: 2668 . y - the result 2669 2670 Level: beginner 2671 2672 Note: 2673 The vectors `x` and `y` cannot be the same. I.e., one cannot 2674 call `MatMult`(A,y,y). 2675 2676 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2677 @*/ 2678 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2679 { 2680 PetscFunctionBegin; 2681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2682 PetscValidType(mat, 1); 2683 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2684 VecCheckAssembled(x); 2685 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2686 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2687 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2688 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2689 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); 2690 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); 2691 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); 2692 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); 2693 PetscCall(VecSetErrorIfLocked(y, 3)); 2694 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2695 MatCheckPreallocated(mat, 1); 2696 2697 PetscCall(VecLockReadPush(x)); 2698 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2699 PetscUseTypeMethod(mat, mult, x, y); 2700 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2701 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2702 PetscCall(VecLockReadPop(x)); 2703 PetscFunctionReturn(PETSC_SUCCESS); 2704 } 2705 2706 /*@ 2707 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2708 2709 Neighbor-wise Collective 2710 2711 Input Parameters: 2712 + mat - the matrix 2713 - x - the vector to be multiplied 2714 2715 Output Parameter: 2716 . y - the result 2717 2718 Level: beginner 2719 2720 Notes: 2721 The vectors `x` and `y` cannot be the same. I.e., one cannot 2722 call `MatMultTranspose`(A,y,y). 2723 2724 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2725 use `MatMultHermitianTranspose()` 2726 2727 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2728 @*/ 2729 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2730 { 2731 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2732 2733 PetscFunctionBegin; 2734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2735 PetscValidType(mat, 1); 2736 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2737 VecCheckAssembled(x); 2738 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2739 2740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2742 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2743 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); 2744 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); 2745 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); 2746 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); 2747 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2748 MatCheckPreallocated(mat, 1); 2749 2750 if (!mat->ops->multtranspose) { 2751 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2752 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); 2753 } else op = mat->ops->multtranspose; 2754 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2755 PetscCall(VecLockReadPush(x)); 2756 PetscCall((*op)(mat, x, y)); 2757 PetscCall(VecLockReadPop(x)); 2758 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2759 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2760 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2761 PetscFunctionReturn(PETSC_SUCCESS); 2762 } 2763 2764 /*@ 2765 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2766 2767 Neighbor-wise Collective 2768 2769 Input Parameters: 2770 + mat - the matrix 2771 - x - the vector to be multiplied 2772 2773 Output Parameter: 2774 . y - the result 2775 2776 Level: beginner 2777 2778 Notes: 2779 The vectors `x` and `y` cannot be the same. I.e., one cannot 2780 call `MatMultHermitianTranspose`(A,y,y). 2781 2782 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2783 2784 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2785 2786 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2787 @*/ 2788 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2789 { 2790 PetscFunctionBegin; 2791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2792 PetscValidType(mat, 1); 2793 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2794 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2795 2796 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2797 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2798 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2799 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); 2800 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); 2801 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); 2802 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); 2803 MatCheckPreallocated(mat, 1); 2804 2805 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2806 #if defined(PETSC_USE_COMPLEX) 2807 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2808 PetscCall(VecLockReadPush(x)); 2809 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2810 else PetscUseTypeMethod(mat, mult, x, y); 2811 PetscCall(VecLockReadPop(x)); 2812 } else { 2813 Vec w; 2814 PetscCall(VecDuplicate(x, &w)); 2815 PetscCall(VecCopy(x, w)); 2816 PetscCall(VecConjugate(w)); 2817 PetscCall(MatMultTranspose(mat, w, y)); 2818 PetscCall(VecDestroy(&w)); 2819 PetscCall(VecConjugate(y)); 2820 } 2821 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2822 #else 2823 PetscCall(MatMultTranspose(mat, x, y)); 2824 #endif 2825 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2826 PetscFunctionReturn(PETSC_SUCCESS); 2827 } 2828 2829 /*@ 2830 MatMultAdd - Computes $v3 = v2 + A * v1$. 2831 2832 Neighbor-wise Collective 2833 2834 Input Parameters: 2835 + mat - the matrix 2836 . v1 - the vector to be multiplied by `mat` 2837 - v2 - the vector to be added to the result 2838 2839 Output Parameter: 2840 . v3 - the result 2841 2842 Level: beginner 2843 2844 Note: 2845 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2846 call `MatMultAdd`(A,v1,v2,v1). 2847 2848 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2849 @*/ 2850 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2851 { 2852 PetscFunctionBegin; 2853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2854 PetscValidType(mat, 1); 2855 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2856 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2857 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2858 2859 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2860 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2861 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); 2862 /* 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); 2863 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); */ 2864 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); 2865 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); 2866 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2867 MatCheckPreallocated(mat, 1); 2868 2869 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2870 PetscCall(VecLockReadPush(v1)); 2871 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2872 PetscCall(VecLockReadPop(v1)); 2873 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2874 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2875 PetscFunctionReturn(PETSC_SUCCESS); 2876 } 2877 2878 /*@ 2879 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2880 2881 Neighbor-wise Collective 2882 2883 Input Parameters: 2884 + mat - the matrix 2885 . v1 - the vector to be multiplied by the transpose of the matrix 2886 - v2 - the vector to be added to the result 2887 2888 Output Parameter: 2889 . v3 - the result 2890 2891 Level: beginner 2892 2893 Note: 2894 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2895 call `MatMultTransposeAdd`(A,v1,v2,v1). 2896 2897 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2898 @*/ 2899 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2900 { 2901 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2902 2903 PetscFunctionBegin; 2904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2905 PetscValidType(mat, 1); 2906 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2907 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2908 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2909 2910 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2911 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2912 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); 2913 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); 2914 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); 2915 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2916 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2917 MatCheckPreallocated(mat, 1); 2918 2919 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2920 PetscCall(VecLockReadPush(v1)); 2921 PetscCall((*op)(mat, v1, v2, v3)); 2922 PetscCall(VecLockReadPop(v1)); 2923 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2924 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2925 PetscFunctionReturn(PETSC_SUCCESS); 2926 } 2927 2928 /*@ 2929 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2930 2931 Neighbor-wise Collective 2932 2933 Input Parameters: 2934 + mat - the matrix 2935 . v1 - the vector to be multiplied by the Hermitian transpose 2936 - v2 - the vector to be added to the result 2937 2938 Output Parameter: 2939 . v3 - the result 2940 2941 Level: beginner 2942 2943 Note: 2944 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2945 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2946 2947 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2948 @*/ 2949 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2950 { 2951 PetscFunctionBegin; 2952 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2953 PetscValidType(mat, 1); 2954 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2955 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2956 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2957 2958 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2959 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2960 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2961 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); 2962 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); 2963 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); 2964 MatCheckPreallocated(mat, 1); 2965 2966 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2967 PetscCall(VecLockReadPush(v1)); 2968 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2969 else { 2970 Vec w, z; 2971 PetscCall(VecDuplicate(v1, &w)); 2972 PetscCall(VecCopy(v1, w)); 2973 PetscCall(VecConjugate(w)); 2974 PetscCall(VecDuplicate(v3, &z)); 2975 PetscCall(MatMultTranspose(mat, w, z)); 2976 PetscCall(VecDestroy(&w)); 2977 PetscCall(VecConjugate(z)); 2978 if (v2 != v3) { 2979 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2980 } else { 2981 PetscCall(VecAXPY(v3, 1.0, z)); 2982 } 2983 PetscCall(VecDestroy(&z)); 2984 } 2985 PetscCall(VecLockReadPop(v1)); 2986 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2987 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2988 PetscFunctionReturn(PETSC_SUCCESS); 2989 } 2990 2991 /*@ 2992 MatGetFactorType - gets the type of factorization a matrix is 2993 2994 Not Collective 2995 2996 Input Parameter: 2997 . mat - the matrix 2998 2999 Output Parameter: 3000 . 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` 3001 3002 Level: intermediate 3003 3004 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3005 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3006 @*/ 3007 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3008 { 3009 PetscFunctionBegin; 3010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3011 PetscValidType(mat, 1); 3012 PetscAssertPointer(t, 2); 3013 *t = mat->factortype; 3014 PetscFunctionReturn(PETSC_SUCCESS); 3015 } 3016 3017 /*@ 3018 MatSetFactorType - sets the type of factorization a matrix is 3019 3020 Logically Collective 3021 3022 Input Parameters: 3023 + mat - the matrix 3024 - 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` 3025 3026 Level: intermediate 3027 3028 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3029 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3030 @*/ 3031 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3032 { 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 PetscValidType(mat, 1); 3036 mat->factortype = t; 3037 PetscFunctionReturn(PETSC_SUCCESS); 3038 } 3039 3040 /*@ 3041 MatGetInfo - Returns information about matrix storage (number of 3042 nonzeros, memory, etc.). 3043 3044 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3045 3046 Input Parameters: 3047 + mat - the matrix 3048 - 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) 3049 3050 Output Parameter: 3051 . info - matrix information context 3052 3053 Options Database Key: 3054 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3055 3056 Level: intermediate 3057 3058 Notes: 3059 The `MatInfo` context contains a variety of matrix data, including 3060 number of nonzeros allocated and used, number of mallocs during 3061 matrix assembly, etc. Additional information for factored matrices 3062 is provided (such as the fill ratio, number of mallocs during 3063 factorization, etc.). 3064 3065 Example: 3066 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3067 data within the `MatInfo` context. For example, 3068 .vb 3069 MatInfo info; 3070 Mat A; 3071 double mal, nz_a, nz_u; 3072 3073 MatGetInfo(A, MAT_LOCAL, &info); 3074 mal = info.mallocs; 3075 nz_a = info.nz_allocated; 3076 .ve 3077 3078 Fortran Note: 3079 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3080 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3081 a complete list of parameter names. 3082 .vb 3083 MatInfo info(MAT_INFO_SIZE) 3084 double precision mal, nz_a 3085 Mat A 3086 integer ierr 3087 3088 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3089 mal = info(MAT_INFO_MALLOCS) 3090 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3091 .ve 3092 3093 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3094 @*/ 3095 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3096 { 3097 PetscFunctionBegin; 3098 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3099 PetscValidType(mat, 1); 3100 PetscAssertPointer(info, 3); 3101 MatCheckPreallocated(mat, 1); 3102 PetscUseTypeMethod(mat, getinfo, flag, info); 3103 PetscFunctionReturn(PETSC_SUCCESS); 3104 } 3105 3106 /* 3107 This is used by external packages where it is not easy to get the info from the actual 3108 matrix factorization. 3109 */ 3110 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3111 { 3112 PetscFunctionBegin; 3113 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3114 PetscFunctionReturn(PETSC_SUCCESS); 3115 } 3116 3117 /*@ 3118 MatLUFactor - Performs in-place LU factorization of matrix. 3119 3120 Collective 3121 3122 Input Parameters: 3123 + mat - the matrix 3124 . row - row permutation 3125 . col - column permutation 3126 - info - options for factorization, includes 3127 .vb 3128 fill - expected fill as ratio of original fill. 3129 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3130 Run with the option -info to determine an optimal value to use 3131 .ve 3132 3133 Level: developer 3134 3135 Notes: 3136 Most users should employ the `KSP` interface for linear solvers 3137 instead of working directly with matrix algebra routines such as this. 3138 See, e.g., `KSPCreate()`. 3139 3140 This changes the state of the matrix to a factored matrix; it cannot be used 3141 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3142 3143 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3144 when not using `KSP`. 3145 3146 Developer Note: 3147 The Fortran interface is not autogenerated as the 3148 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3149 3150 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3151 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3152 @*/ 3153 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3154 { 3155 MatFactorInfo tinfo; 3156 3157 PetscFunctionBegin; 3158 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3159 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3160 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3161 if (info) PetscAssertPointer(info, 4); 3162 PetscValidType(mat, 1); 3163 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3164 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3165 MatCheckPreallocated(mat, 1); 3166 if (!info) { 3167 PetscCall(MatFactorInfoInitialize(&tinfo)); 3168 info = &tinfo; 3169 } 3170 3171 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3172 PetscUseTypeMethod(mat, lufactor, row, col, info); 3173 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3174 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3175 PetscFunctionReturn(PETSC_SUCCESS); 3176 } 3177 3178 /*@ 3179 MatILUFactor - Performs in-place ILU factorization of matrix. 3180 3181 Collective 3182 3183 Input Parameters: 3184 + mat - the matrix 3185 . row - row permutation 3186 . col - column permutation 3187 - info - structure containing 3188 .vb 3189 levels - number of levels of fill. 3190 expected fill - as ratio of original fill. 3191 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3192 missing diagonal entries) 3193 .ve 3194 3195 Level: developer 3196 3197 Notes: 3198 Most users should employ the `KSP` interface for linear solvers 3199 instead of working directly with matrix algebra routines such as this. 3200 See, e.g., `KSPCreate()`. 3201 3202 Probably really in-place only when level of fill is zero, otherwise allocates 3203 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3204 when not using `KSP`. 3205 3206 Developer Note: 3207 The Fortran interface is not autogenerated as the 3208 interface definition cannot be generated correctly [due to MatFactorInfo] 3209 3210 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3211 @*/ 3212 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3213 { 3214 PetscFunctionBegin; 3215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3216 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3217 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3218 PetscAssertPointer(info, 4); 3219 PetscValidType(mat, 1); 3220 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3221 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3222 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3223 MatCheckPreallocated(mat, 1); 3224 3225 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3226 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3227 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3228 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3229 PetscFunctionReturn(PETSC_SUCCESS); 3230 } 3231 3232 /*@ 3233 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3234 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3235 3236 Collective 3237 3238 Input Parameters: 3239 + fact - the factor matrix obtained with `MatGetFactor()` 3240 . mat - the matrix 3241 . row - the row permutation 3242 . col - the column permutation 3243 - info - options for factorization, includes 3244 .vb 3245 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3246 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3247 .ve 3248 3249 Level: developer 3250 3251 Notes: 3252 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3253 3254 Most users should employ the simplified `KSP` interface for linear solvers 3255 instead of working directly with matrix algebra routines such as this. 3256 See, e.g., `KSPCreate()`. 3257 3258 Developer Note: 3259 The Fortran interface is not autogenerated as the 3260 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3261 3262 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3263 @*/ 3264 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3265 { 3266 MatFactorInfo tinfo; 3267 3268 PetscFunctionBegin; 3269 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3271 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3272 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3273 if (info) PetscAssertPointer(info, 5); 3274 PetscValidType(fact, 1); 3275 PetscValidType(mat, 2); 3276 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3277 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3278 MatCheckPreallocated(mat, 2); 3279 if (!info) { 3280 PetscCall(MatFactorInfoInitialize(&tinfo)); 3281 info = &tinfo; 3282 } 3283 3284 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3285 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3286 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3287 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3288 PetscFunctionReturn(PETSC_SUCCESS); 3289 } 3290 3291 /*@ 3292 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3293 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3294 3295 Collective 3296 3297 Input Parameters: 3298 + fact - the factor matrix obtained with `MatGetFactor()` 3299 . mat - the matrix 3300 - info - options for factorization 3301 3302 Level: developer 3303 3304 Notes: 3305 See `MatLUFactor()` for in-place factorization. See 3306 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3307 3308 Most users should employ the `KSP` interface for linear solvers 3309 instead of working directly with matrix algebra routines such as this. 3310 See, e.g., `KSPCreate()`. 3311 3312 Developer Note: 3313 The Fortran interface is not autogenerated as the 3314 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3315 3316 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3317 @*/ 3318 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3319 { 3320 MatFactorInfo tinfo; 3321 3322 PetscFunctionBegin; 3323 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3325 PetscValidType(fact, 1); 3326 PetscValidType(mat, 2); 3327 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3328 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, 3329 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3330 3331 MatCheckPreallocated(mat, 2); 3332 if (!info) { 3333 PetscCall(MatFactorInfoInitialize(&tinfo)); 3334 info = &tinfo; 3335 } 3336 3337 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3338 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3339 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3340 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3341 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3342 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3343 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3344 PetscFunctionReturn(PETSC_SUCCESS); 3345 } 3346 3347 /*@ 3348 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3349 symmetric matrix. 3350 3351 Collective 3352 3353 Input Parameters: 3354 + mat - the matrix 3355 . perm - row and column permutations 3356 - info - expected fill as ratio of original fill 3357 3358 Level: developer 3359 3360 Notes: 3361 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3362 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3363 3364 Most users should employ the `KSP` interface for linear solvers 3365 instead of working directly with matrix algebra routines such as this. 3366 See, e.g., `KSPCreate()`. 3367 3368 Developer Note: 3369 The Fortran interface is not autogenerated as the 3370 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3371 3372 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3373 `MatGetOrdering()` 3374 @*/ 3375 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3376 { 3377 MatFactorInfo tinfo; 3378 3379 PetscFunctionBegin; 3380 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3381 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3382 if (info) PetscAssertPointer(info, 3); 3383 PetscValidType(mat, 1); 3384 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3385 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3386 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3387 MatCheckPreallocated(mat, 1); 3388 if (!info) { 3389 PetscCall(MatFactorInfoInitialize(&tinfo)); 3390 info = &tinfo; 3391 } 3392 3393 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3394 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3395 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3396 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3397 PetscFunctionReturn(PETSC_SUCCESS); 3398 } 3399 3400 /*@ 3401 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3402 of a symmetric matrix. 3403 3404 Collective 3405 3406 Input Parameters: 3407 + fact - the factor matrix obtained with `MatGetFactor()` 3408 . mat - the matrix 3409 . perm - row and column permutations 3410 - info - options for factorization, includes 3411 .vb 3412 fill - expected fill as ratio of original fill. 3413 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3414 Run with the option -info to determine an optimal value to use 3415 .ve 3416 3417 Level: developer 3418 3419 Notes: 3420 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3421 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3422 3423 Most users should employ the `KSP` interface for linear solvers 3424 instead of working directly with matrix algebra routines such as this. 3425 See, e.g., `KSPCreate()`. 3426 3427 Developer Note: 3428 The Fortran interface is not autogenerated as the 3429 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3430 3431 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3432 `MatGetOrdering()` 3433 @*/ 3434 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3435 { 3436 MatFactorInfo tinfo; 3437 3438 PetscFunctionBegin; 3439 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3440 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3441 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3442 if (info) PetscAssertPointer(info, 4); 3443 PetscValidType(fact, 1); 3444 PetscValidType(mat, 2); 3445 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3446 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3447 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3448 MatCheckPreallocated(mat, 2); 3449 if (!info) { 3450 PetscCall(MatFactorInfoInitialize(&tinfo)); 3451 info = &tinfo; 3452 } 3453 3454 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3455 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3456 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3457 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3458 PetscFunctionReturn(PETSC_SUCCESS); 3459 } 3460 3461 /*@ 3462 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3463 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3464 `MatCholeskyFactorSymbolic()`. 3465 3466 Collective 3467 3468 Input Parameters: 3469 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3470 . mat - the initial matrix that is to be factored 3471 - info - options for factorization 3472 3473 Level: developer 3474 3475 Note: 3476 Most users should employ the `KSP` interface for linear solvers 3477 instead of working directly with matrix algebra routines such as this. 3478 See, e.g., `KSPCreate()`. 3479 3480 Developer Note: 3481 The Fortran interface is not autogenerated as the 3482 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3483 3484 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3485 @*/ 3486 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3487 { 3488 MatFactorInfo tinfo; 3489 3490 PetscFunctionBegin; 3491 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3492 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3493 PetscValidType(fact, 1); 3494 PetscValidType(mat, 2); 3495 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3496 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, 3497 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3498 MatCheckPreallocated(mat, 2); 3499 if (!info) { 3500 PetscCall(MatFactorInfoInitialize(&tinfo)); 3501 info = &tinfo; 3502 } 3503 3504 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3505 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3506 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3507 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3508 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3509 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3510 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3511 PetscFunctionReturn(PETSC_SUCCESS); 3512 } 3513 3514 /*@ 3515 MatQRFactor - Performs in-place QR factorization of matrix. 3516 3517 Collective 3518 3519 Input Parameters: 3520 + mat - the matrix 3521 . col - column permutation 3522 - info - options for factorization, includes 3523 .vb 3524 fill - expected fill as ratio of original fill. 3525 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3526 Run with the option -info to determine an optimal value to use 3527 .ve 3528 3529 Level: developer 3530 3531 Notes: 3532 Most users should employ the `KSP` interface for linear solvers 3533 instead of working directly with matrix algebra routines such as this. 3534 See, e.g., `KSPCreate()`. 3535 3536 This changes the state of the matrix to a factored matrix; it cannot be used 3537 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3538 3539 Developer Note: 3540 The Fortran interface is not autogenerated as the 3541 interface definition cannot be generated correctly [due to MatFactorInfo] 3542 3543 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3544 `MatSetUnfactored()` 3545 @*/ 3546 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3547 { 3548 PetscFunctionBegin; 3549 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3550 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3551 if (info) PetscAssertPointer(info, 3); 3552 PetscValidType(mat, 1); 3553 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3554 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3555 MatCheckPreallocated(mat, 1); 3556 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3557 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3558 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3559 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3560 PetscFunctionReturn(PETSC_SUCCESS); 3561 } 3562 3563 /*@ 3564 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3565 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3566 3567 Collective 3568 3569 Input Parameters: 3570 + fact - the factor matrix obtained with `MatGetFactor()` 3571 . mat - the matrix 3572 . col - column permutation 3573 - info - options for factorization, includes 3574 .vb 3575 fill - expected fill as ratio of original fill. 3576 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3577 Run with the option -info to determine an optimal value to use 3578 .ve 3579 3580 Level: developer 3581 3582 Note: 3583 Most users should employ the `KSP` interface for linear solvers 3584 instead of working directly with matrix algebra routines such as this. 3585 See, e.g., `KSPCreate()`. 3586 3587 Developer Note: 3588 The Fortran interface is not autogenerated as the 3589 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3590 3591 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3592 @*/ 3593 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3594 { 3595 MatFactorInfo tinfo; 3596 3597 PetscFunctionBegin; 3598 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3600 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3601 if (info) PetscAssertPointer(info, 4); 3602 PetscValidType(fact, 1); 3603 PetscValidType(mat, 2); 3604 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3605 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3606 MatCheckPreallocated(mat, 2); 3607 if (!info) { 3608 PetscCall(MatFactorInfoInitialize(&tinfo)); 3609 info = &tinfo; 3610 } 3611 3612 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3613 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3614 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3615 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3616 PetscFunctionReturn(PETSC_SUCCESS); 3617 } 3618 3619 /*@ 3620 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3621 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3622 3623 Collective 3624 3625 Input Parameters: 3626 + fact - the factor matrix obtained with `MatGetFactor()` 3627 . mat - the matrix 3628 - info - options for factorization 3629 3630 Level: developer 3631 3632 Notes: 3633 See `MatQRFactor()` for in-place factorization. 3634 3635 Most users should employ the `KSP` interface for linear solvers 3636 instead of working directly with matrix algebra routines such as this. 3637 See, e.g., `KSPCreate()`. 3638 3639 Developer Note: 3640 The Fortran interface is not autogenerated as the 3641 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3642 3643 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3644 @*/ 3645 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3646 { 3647 MatFactorInfo tinfo; 3648 3649 PetscFunctionBegin; 3650 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3651 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3652 PetscValidType(fact, 1); 3653 PetscValidType(mat, 2); 3654 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3655 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, 3656 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3657 3658 MatCheckPreallocated(mat, 2); 3659 if (!info) { 3660 PetscCall(MatFactorInfoInitialize(&tinfo)); 3661 info = &tinfo; 3662 } 3663 3664 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3665 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3666 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3667 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3668 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3669 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3670 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3671 PetscFunctionReturn(PETSC_SUCCESS); 3672 } 3673 3674 /*@ 3675 MatSolve - Solves $A x = b$, given a factored matrix. 3676 3677 Neighbor-wise Collective 3678 3679 Input Parameters: 3680 + mat - the factored matrix 3681 - b - the right-hand-side vector 3682 3683 Output Parameter: 3684 . x - the result vector 3685 3686 Level: developer 3687 3688 Notes: 3689 The vectors `b` and `x` cannot be the same. I.e., one cannot 3690 call `MatSolve`(A,x,x). 3691 3692 Most users should employ the `KSP` interface for linear solvers 3693 instead of working directly with matrix algebra routines such as this. 3694 See, e.g., `KSPCreate()`. 3695 3696 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3697 @*/ 3698 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3699 { 3700 PetscFunctionBegin; 3701 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3702 PetscValidType(mat, 1); 3703 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3704 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3705 PetscCheckSameComm(mat, 1, b, 2); 3706 PetscCheckSameComm(mat, 1, x, 3); 3707 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3708 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); 3709 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); 3710 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); 3711 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3712 MatCheckPreallocated(mat, 1); 3713 3714 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3715 PetscCall(VecFlag(x, mat->factorerrortype)); 3716 if (mat->factorerrortype) { 3717 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3718 } else PetscUseTypeMethod(mat, solve, b, x); 3719 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3720 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3721 PetscFunctionReturn(PETSC_SUCCESS); 3722 } 3723 3724 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3725 { 3726 Vec b, x; 3727 PetscInt N, i; 3728 PetscErrorCode (*f)(Mat, Vec, Vec); 3729 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3730 3731 PetscFunctionBegin; 3732 if (A->factorerrortype) { 3733 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3734 PetscCall(MatSetInf(X)); 3735 PetscFunctionReturn(PETSC_SUCCESS); 3736 } 3737 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3738 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3739 PetscCall(MatBoundToCPU(A, &Abound)); 3740 if (!Abound) { 3741 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3742 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3743 } 3744 #if PetscDefined(HAVE_CUDA) 3745 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3746 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3747 #elif PetscDefined(HAVE_HIP) 3748 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3749 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3750 #endif 3751 PetscCall(MatGetSize(B, NULL, &N)); 3752 for (i = 0; i < N; i++) { 3753 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3754 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3755 PetscCall((*f)(A, b, x)); 3756 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3757 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3758 } 3759 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3760 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3761 PetscFunctionReturn(PETSC_SUCCESS); 3762 } 3763 3764 /*@ 3765 MatMatSolve - Solves $A X = B$, given a factored matrix. 3766 3767 Neighbor-wise Collective 3768 3769 Input Parameters: 3770 + A - the factored matrix 3771 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3772 3773 Output Parameter: 3774 . X - the result matrix (dense matrix) 3775 3776 Level: developer 3777 3778 Note: 3779 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3780 otherwise, `B` and `X` cannot be the same. 3781 3782 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3783 @*/ 3784 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3785 { 3786 PetscFunctionBegin; 3787 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3788 PetscValidType(A, 1); 3789 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3790 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3791 PetscCheckSameComm(A, 1, B, 2); 3792 PetscCheckSameComm(A, 1, X, 3); 3793 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); 3794 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); 3795 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"); 3796 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3797 MatCheckPreallocated(A, 1); 3798 3799 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3800 if (!A->ops->matsolve) { 3801 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3802 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3803 } else PetscUseTypeMethod(A, matsolve, B, X); 3804 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3805 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3806 PetscFunctionReturn(PETSC_SUCCESS); 3807 } 3808 3809 /*@ 3810 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3811 3812 Neighbor-wise Collective 3813 3814 Input Parameters: 3815 + A - the factored matrix 3816 - B - the right-hand-side matrix (`MATDENSE` matrix) 3817 3818 Output Parameter: 3819 . X - the result matrix (dense matrix) 3820 3821 Level: developer 3822 3823 Note: 3824 The matrices `B` and `X` cannot be the same. I.e., one cannot 3825 call `MatMatSolveTranspose`(A,X,X). 3826 3827 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3828 @*/ 3829 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3830 { 3831 PetscFunctionBegin; 3832 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3833 PetscValidType(A, 1); 3834 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3835 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3836 PetscCheckSameComm(A, 1, B, 2); 3837 PetscCheckSameComm(A, 1, X, 3); 3838 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3839 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); 3840 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); 3841 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); 3842 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"); 3843 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3844 MatCheckPreallocated(A, 1); 3845 3846 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3847 if (!A->ops->matsolvetranspose) { 3848 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3849 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3850 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3851 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3852 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3853 PetscFunctionReturn(PETSC_SUCCESS); 3854 } 3855 3856 /*@ 3857 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3858 3859 Neighbor-wise Collective 3860 3861 Input Parameters: 3862 + A - the factored matrix 3863 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3864 3865 Output Parameter: 3866 . X - the result matrix (dense matrix) 3867 3868 Level: developer 3869 3870 Note: 3871 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 3872 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3873 3874 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3875 @*/ 3876 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3877 { 3878 PetscFunctionBegin; 3879 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3880 PetscValidType(A, 1); 3881 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3882 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3883 PetscCheckSameComm(A, 1, Bt, 2); 3884 PetscCheckSameComm(A, 1, X, 3); 3885 3886 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3887 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); 3888 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); 3889 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"); 3890 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3891 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3892 MatCheckPreallocated(A, 1); 3893 3894 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3895 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3896 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3897 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3898 PetscFunctionReturn(PETSC_SUCCESS); 3899 } 3900 3901 /*@ 3902 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3903 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3904 3905 Neighbor-wise Collective 3906 3907 Input Parameters: 3908 + mat - the factored matrix 3909 - b - the right-hand-side vector 3910 3911 Output Parameter: 3912 . x - the result vector 3913 3914 Level: developer 3915 3916 Notes: 3917 `MatSolve()` should be used for most applications, as it performs 3918 a forward solve followed by a backward solve. 3919 3920 The vectors `b` and `x` cannot be the same, i.e., one cannot 3921 call `MatForwardSolve`(A,x,x). 3922 3923 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3924 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3925 `MatForwardSolve()` solves $U^T*D y = b$, and 3926 `MatBackwardSolve()` solves $U x = y$. 3927 Thus they do not provide a symmetric preconditioner. 3928 3929 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3930 @*/ 3931 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3932 { 3933 PetscFunctionBegin; 3934 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3935 PetscValidType(mat, 1); 3936 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3937 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3938 PetscCheckSameComm(mat, 1, b, 2); 3939 PetscCheckSameComm(mat, 1, x, 3); 3940 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3941 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); 3942 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); 3943 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); 3944 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3945 MatCheckPreallocated(mat, 1); 3946 3947 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3948 PetscUseTypeMethod(mat, forwardsolve, b, x); 3949 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3950 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3951 PetscFunctionReturn(PETSC_SUCCESS); 3952 } 3953 3954 /*@ 3955 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3956 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3957 3958 Neighbor-wise Collective 3959 3960 Input Parameters: 3961 + mat - the factored matrix 3962 - b - the right-hand-side vector 3963 3964 Output Parameter: 3965 . x - the result vector 3966 3967 Level: developer 3968 3969 Notes: 3970 `MatSolve()` should be used for most applications, as it performs 3971 a forward solve followed by a backward solve. 3972 3973 The vectors `b` and `x` cannot be the same. I.e., one cannot 3974 call `MatBackwardSolve`(A,x,x). 3975 3976 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3977 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3978 `MatForwardSolve()` solves $U^T*D y = b$, and 3979 `MatBackwardSolve()` solves $U x = y$. 3980 Thus they do not provide a symmetric preconditioner. 3981 3982 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3983 @*/ 3984 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3985 { 3986 PetscFunctionBegin; 3987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3988 PetscValidType(mat, 1); 3989 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3990 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3991 PetscCheckSameComm(mat, 1, b, 2); 3992 PetscCheckSameComm(mat, 1, x, 3); 3993 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3994 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); 3995 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); 3996 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); 3997 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3998 MatCheckPreallocated(mat, 1); 3999 4000 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 4001 PetscUseTypeMethod(mat, backwardsolve, b, x); 4002 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 4003 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4004 PetscFunctionReturn(PETSC_SUCCESS); 4005 } 4006 4007 /*@ 4008 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4009 4010 Neighbor-wise Collective 4011 4012 Input Parameters: 4013 + mat - the factored matrix 4014 . b - the right-hand-side vector 4015 - y - the vector to be added to 4016 4017 Output Parameter: 4018 . x - the result vector 4019 4020 Level: developer 4021 4022 Note: 4023 The vectors `b` and `x` cannot be the same. I.e., one cannot 4024 call `MatSolveAdd`(A,x,y,x). 4025 4026 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4027 @*/ 4028 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4029 { 4030 PetscScalar one = 1.0; 4031 Vec tmp; 4032 4033 PetscFunctionBegin; 4034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4035 PetscValidType(mat, 1); 4036 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4037 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4038 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4039 PetscCheckSameComm(mat, 1, b, 2); 4040 PetscCheckSameComm(mat, 1, y, 3); 4041 PetscCheckSameComm(mat, 1, x, 4); 4042 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4043 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); 4044 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); 4045 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); 4046 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); 4047 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); 4048 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4049 MatCheckPreallocated(mat, 1); 4050 4051 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4052 PetscCall(VecFlag(x, mat->factorerrortype)); 4053 if (mat->factorerrortype) { 4054 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4055 } else if (mat->ops->solveadd) { 4056 PetscUseTypeMethod(mat, solveadd, b, y, x); 4057 } else { 4058 /* do the solve then the add manually */ 4059 if (x != y) { 4060 PetscCall(MatSolve(mat, b, x)); 4061 PetscCall(VecAXPY(x, one, y)); 4062 } else { 4063 PetscCall(VecDuplicate(x, &tmp)); 4064 PetscCall(VecCopy(x, tmp)); 4065 PetscCall(MatSolve(mat, b, x)); 4066 PetscCall(VecAXPY(x, one, tmp)); 4067 PetscCall(VecDestroy(&tmp)); 4068 } 4069 } 4070 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4071 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4072 PetscFunctionReturn(PETSC_SUCCESS); 4073 } 4074 4075 /*@ 4076 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4077 4078 Neighbor-wise Collective 4079 4080 Input Parameters: 4081 + mat - the factored matrix 4082 - b - the right-hand-side vector 4083 4084 Output Parameter: 4085 . x - the result vector 4086 4087 Level: developer 4088 4089 Notes: 4090 The vectors `b` and `x` cannot be the same. I.e., one cannot 4091 call `MatSolveTranspose`(A,x,x). 4092 4093 Most users should employ the `KSP` interface for linear solvers 4094 instead of working directly with matrix algebra routines such as this. 4095 See, e.g., `KSPCreate()`. 4096 4097 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4098 @*/ 4099 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4100 { 4101 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4102 4103 PetscFunctionBegin; 4104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4105 PetscValidType(mat, 1); 4106 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4107 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4108 PetscCheckSameComm(mat, 1, b, 2); 4109 PetscCheckSameComm(mat, 1, x, 3); 4110 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4111 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); 4112 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); 4113 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4114 MatCheckPreallocated(mat, 1); 4115 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4116 PetscCall(VecFlag(x, mat->factorerrortype)); 4117 if (mat->factorerrortype) { 4118 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4119 } else { 4120 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4121 PetscCall((*f)(mat, b, x)); 4122 } 4123 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4124 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4125 PetscFunctionReturn(PETSC_SUCCESS); 4126 } 4127 4128 /*@ 4129 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4130 factored matrix. 4131 4132 Neighbor-wise Collective 4133 4134 Input Parameters: 4135 + mat - the factored matrix 4136 . b - the right-hand-side vector 4137 - y - the vector to be added to 4138 4139 Output Parameter: 4140 . x - the result vector 4141 4142 Level: developer 4143 4144 Note: 4145 The vectors `b` and `x` cannot be the same. I.e., one cannot 4146 call `MatSolveTransposeAdd`(A,x,y,x). 4147 4148 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4149 @*/ 4150 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4151 { 4152 PetscScalar one = 1.0; 4153 Vec tmp; 4154 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4155 4156 PetscFunctionBegin; 4157 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4158 PetscValidType(mat, 1); 4159 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4160 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4161 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4162 PetscCheckSameComm(mat, 1, b, 2); 4163 PetscCheckSameComm(mat, 1, y, 3); 4164 PetscCheckSameComm(mat, 1, x, 4); 4165 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4166 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); 4167 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); 4168 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); 4169 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); 4170 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4171 MatCheckPreallocated(mat, 1); 4172 4173 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4174 PetscCall(VecFlag(x, mat->factorerrortype)); 4175 if (mat->factorerrortype) { 4176 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4177 } else if (f) { 4178 PetscCall((*f)(mat, b, y, x)); 4179 } else { 4180 /* do the solve then the add manually */ 4181 if (x != y) { 4182 PetscCall(MatSolveTranspose(mat, b, x)); 4183 PetscCall(VecAXPY(x, one, y)); 4184 } else { 4185 PetscCall(VecDuplicate(x, &tmp)); 4186 PetscCall(VecCopy(x, tmp)); 4187 PetscCall(MatSolveTranspose(mat, b, x)); 4188 PetscCall(VecAXPY(x, one, tmp)); 4189 PetscCall(VecDestroy(&tmp)); 4190 } 4191 } 4192 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4193 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4194 PetscFunctionReturn(PETSC_SUCCESS); 4195 } 4196 4197 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4198 /*@ 4199 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4200 4201 Neighbor-wise Collective 4202 4203 Input Parameters: 4204 + mat - the matrix 4205 . b - the right-hand side 4206 . omega - the relaxation factor 4207 . flag - flag indicating the type of SOR (see below) 4208 . shift - diagonal shift 4209 . its - the number of iterations 4210 - lits - the number of local iterations 4211 4212 Output Parameter: 4213 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4214 4215 SOR Flags: 4216 + `SOR_FORWARD_SWEEP` - forward SOR 4217 . `SOR_BACKWARD_SWEEP` - backward SOR 4218 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4219 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4220 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4221 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4222 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4223 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4224 upper/lower triangular part of matrix to 4225 vector (with omega) 4226 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4227 4228 Level: developer 4229 4230 Notes: 4231 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4232 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4233 on each processor. 4234 4235 Application programmers will not generally use `MatSOR()` directly, 4236 but instead will employ the `KSP`/`PC` interface. 4237 4238 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4239 4240 Most users should employ the `KSP` interface for linear solvers 4241 instead of working directly with matrix algebra routines such as this. 4242 See, e.g., `KSPCreate()`. 4243 4244 Vectors `x` and `b` CANNOT be the same 4245 4246 The flags are implemented as bitwise inclusive or operations. 4247 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4248 to specify a zero initial guess for SSOR. 4249 4250 Developer Note: 4251 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4252 4253 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4254 @*/ 4255 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4256 { 4257 PetscFunctionBegin; 4258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4259 PetscValidType(mat, 1); 4260 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4261 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4262 PetscCheckSameComm(mat, 1, b, 2); 4263 PetscCheckSameComm(mat, 1, x, 8); 4264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4265 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4266 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); 4267 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); 4268 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); 4269 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4270 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4271 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4272 4273 MatCheckPreallocated(mat, 1); 4274 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4275 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4276 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4277 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4278 PetscFunctionReturn(PETSC_SUCCESS); 4279 } 4280 4281 /* 4282 Default matrix copy routine. 4283 */ 4284 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4285 { 4286 PetscInt i, rstart = 0, rend = 0, nz; 4287 const PetscInt *cwork; 4288 const PetscScalar *vwork; 4289 4290 PetscFunctionBegin; 4291 if (B->assembled) PetscCall(MatZeroEntries(B)); 4292 if (str == SAME_NONZERO_PATTERN) { 4293 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4294 for (i = rstart; i < rend; i++) { 4295 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4296 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4297 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4298 } 4299 } else { 4300 PetscCall(MatAYPX(B, 0.0, A, str)); 4301 } 4302 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4303 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4304 PetscFunctionReturn(PETSC_SUCCESS); 4305 } 4306 4307 /*@ 4308 MatCopy - Copies a matrix to another matrix. 4309 4310 Collective 4311 4312 Input Parameters: 4313 + A - the matrix 4314 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4315 4316 Output Parameter: 4317 . B - where the copy is put 4318 4319 Level: intermediate 4320 4321 Notes: 4322 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4323 4324 `MatCopy()` copies the matrix entries of a matrix to another existing 4325 matrix (after first zeroing the second matrix). A related routine is 4326 `MatConvert()`, which first creates a new matrix and then copies the data. 4327 4328 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4329 @*/ 4330 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4331 { 4332 PetscInt i; 4333 4334 PetscFunctionBegin; 4335 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4336 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4337 PetscValidType(A, 1); 4338 PetscValidType(B, 2); 4339 PetscCheckSameComm(A, 1, B, 2); 4340 MatCheckPreallocated(B, 2); 4341 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4342 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4343 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, 4344 A->cmap->N, B->cmap->N); 4345 MatCheckPreallocated(A, 1); 4346 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4347 4348 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4349 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4350 else PetscCall(MatCopy_Basic(A, B, str)); 4351 4352 B->stencil.dim = A->stencil.dim; 4353 B->stencil.noc = A->stencil.noc; 4354 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4355 B->stencil.dims[i] = A->stencil.dims[i]; 4356 B->stencil.starts[i] = A->stencil.starts[i]; 4357 } 4358 4359 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4360 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4361 PetscFunctionReturn(PETSC_SUCCESS); 4362 } 4363 4364 /*@ 4365 MatConvert - Converts a matrix to another matrix, either of the same 4366 or different type. 4367 4368 Collective 4369 4370 Input Parameters: 4371 + mat - the matrix 4372 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4373 same type as the original matrix. 4374 - reuse - denotes if the destination matrix is to be created or reused. 4375 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 4376 `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). 4377 4378 Output Parameter: 4379 . M - pointer to place new matrix 4380 4381 Level: intermediate 4382 4383 Notes: 4384 `MatConvert()` first creates a new matrix and then copies the data from 4385 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4386 entries of one matrix to another already existing matrix context. 4387 4388 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4389 the MPI communicator of the generated matrix is always the same as the communicator 4390 of the input matrix. 4391 4392 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4393 @*/ 4394 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4395 { 4396 PetscBool sametype, issame, flg; 4397 PetscBool3 issymmetric, ishermitian; 4398 char convname[256], mtype[256]; 4399 Mat B; 4400 4401 PetscFunctionBegin; 4402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4403 PetscValidType(mat, 1); 4404 PetscAssertPointer(M, 4); 4405 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4406 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4407 MatCheckPreallocated(mat, 1); 4408 4409 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4410 if (flg) newtype = mtype; 4411 4412 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4413 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4414 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4415 if (reuse == MAT_REUSE_MATRIX) { 4416 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4417 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4418 } 4419 4420 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4421 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4422 PetscFunctionReturn(PETSC_SUCCESS); 4423 } 4424 4425 /* Cache Mat options because some converters use MatHeaderReplace */ 4426 issymmetric = mat->symmetric; 4427 ishermitian = mat->hermitian; 4428 4429 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4430 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4431 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4432 } else { 4433 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4434 const char *prefix[3] = {"seq", "mpi", ""}; 4435 PetscInt i; 4436 /* 4437 Order of precedence: 4438 0) See if newtype is a superclass of the current matrix. 4439 1) See if a specialized converter is known to the current matrix. 4440 2) See if a specialized converter is known to the desired matrix class. 4441 3) See if a good general converter is registered for the desired class 4442 (as of 6/27/03 only MATMPIADJ falls into this category). 4443 4) See if a good general converter is known for the current matrix. 4444 5) Use a really basic converter. 4445 */ 4446 4447 /* 0) See if newtype is a superclass of the current matrix. 4448 i.e mat is mpiaij and newtype is aij */ 4449 for (i = 0; i < 2; i++) { 4450 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4451 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4452 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4453 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4454 if (flg) { 4455 if (reuse == MAT_INPLACE_MATRIX) { 4456 PetscCall(PetscInfo(mat, "Early return\n")); 4457 PetscFunctionReturn(PETSC_SUCCESS); 4458 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4459 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4460 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4461 PetscFunctionReturn(PETSC_SUCCESS); 4462 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4463 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4464 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4465 PetscFunctionReturn(PETSC_SUCCESS); 4466 } 4467 } 4468 } 4469 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4470 for (i = 0; i < 3; i++) { 4471 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4472 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4473 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4474 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4475 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4476 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4477 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4478 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4479 if (conv) goto foundconv; 4480 } 4481 4482 /* 2) See if a specialized converter is known to the desired matrix class. */ 4483 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4484 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4485 PetscCall(MatSetType(B, newtype)); 4486 for (i = 0; i < 3; i++) { 4487 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4488 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4489 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4490 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4491 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4492 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4493 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4494 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4495 if (conv) { 4496 PetscCall(MatDestroy(&B)); 4497 goto foundconv; 4498 } 4499 } 4500 4501 /* 3) See if a good general converter is registered for the desired class */ 4502 conv = B->ops->convertfrom; 4503 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4504 PetscCall(MatDestroy(&B)); 4505 if (conv) goto foundconv; 4506 4507 /* 4) See if a good general converter is known for the current matrix */ 4508 if (mat->ops->convert) conv = mat->ops->convert; 4509 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4510 if (conv) goto foundconv; 4511 4512 /* 5) Use a really basic converter. */ 4513 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4514 conv = MatConvert_Basic; 4515 4516 foundconv: 4517 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4518 PetscCall((*conv)(mat, newtype, reuse, M)); 4519 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4520 /* the block sizes must be same if the mappings are copied over */ 4521 (*M)->rmap->bs = mat->rmap->bs; 4522 (*M)->cmap->bs = mat->cmap->bs; 4523 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4524 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4525 (*M)->rmap->mapping = mat->rmap->mapping; 4526 (*M)->cmap->mapping = mat->cmap->mapping; 4527 } 4528 (*M)->stencil.dim = mat->stencil.dim; 4529 (*M)->stencil.noc = mat->stencil.noc; 4530 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4531 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4532 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4533 } 4534 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4535 } 4536 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4537 4538 /* Copy Mat options */ 4539 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4540 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4541 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4542 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4543 PetscFunctionReturn(PETSC_SUCCESS); 4544 } 4545 4546 /*@ 4547 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4548 4549 Not Collective 4550 4551 Input Parameter: 4552 . mat - the matrix, must be a factored matrix 4553 4554 Output Parameter: 4555 . type - the string name of the package (do not free this string) 4556 4557 Level: intermediate 4558 4559 Fortran Note: 4560 Pass in an empty string that is long enough and the package name will be copied into it. 4561 4562 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4563 @*/ 4564 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4565 { 4566 PetscErrorCode (*conv)(Mat, MatSolverType *); 4567 4568 PetscFunctionBegin; 4569 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4570 PetscValidType(mat, 1); 4571 PetscAssertPointer(type, 2); 4572 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4573 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4574 if (conv) PetscCall((*conv)(mat, type)); 4575 else *type = MATSOLVERPETSC; 4576 PetscFunctionReturn(PETSC_SUCCESS); 4577 } 4578 4579 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4580 struct _MatSolverTypeForSpecifcType { 4581 MatType mtype; 4582 /* no entry for MAT_FACTOR_NONE */ 4583 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4584 MatSolverTypeForSpecifcType next; 4585 }; 4586 4587 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4588 struct _MatSolverTypeHolder { 4589 char *name; 4590 MatSolverTypeForSpecifcType handlers; 4591 MatSolverTypeHolder next; 4592 }; 4593 4594 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4595 4596 /*@C 4597 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4598 4599 Logically Collective, No Fortran Support 4600 4601 Input Parameters: 4602 + package - name of the package, for example petsc or superlu 4603 . mtype - the matrix type that works with this package 4604 . ftype - the type of factorization supported by the package 4605 - createfactor - routine that will create the factored matrix ready to be used 4606 4607 Level: developer 4608 4609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4610 `MatGetFactor()` 4611 @*/ 4612 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4613 { 4614 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4615 PetscBool flg; 4616 MatSolverTypeForSpecifcType inext, iprev = NULL; 4617 4618 PetscFunctionBegin; 4619 PetscCall(MatInitializePackage()); 4620 if (!next) { 4621 PetscCall(PetscNew(&MatSolverTypeHolders)); 4622 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4623 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4624 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4625 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4626 PetscFunctionReturn(PETSC_SUCCESS); 4627 } 4628 while (next) { 4629 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4630 if (flg) { 4631 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4632 inext = next->handlers; 4633 while (inext) { 4634 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4635 if (flg) { 4636 inext->createfactor[(int)ftype - 1] = createfactor; 4637 PetscFunctionReturn(PETSC_SUCCESS); 4638 } 4639 iprev = inext; 4640 inext = inext->next; 4641 } 4642 PetscCall(PetscNew(&iprev->next)); 4643 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4644 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4645 PetscFunctionReturn(PETSC_SUCCESS); 4646 } 4647 prev = next; 4648 next = next->next; 4649 } 4650 PetscCall(PetscNew(&prev->next)); 4651 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4652 PetscCall(PetscNew(&prev->next->handlers)); 4653 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4654 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4655 PetscFunctionReturn(PETSC_SUCCESS); 4656 } 4657 4658 /*@C 4659 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4660 4661 Input Parameters: 4662 + 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 4663 . ftype - the type of factorization supported by the type 4664 - mtype - the matrix type that works with this type 4665 4666 Output Parameters: 4667 + foundtype - `PETSC_TRUE` if the type was registered 4668 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4669 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4670 4671 Calling sequence of `createfactor`: 4672 + A - the matrix providing the factor matrix 4673 . ftype - the `MatFactorType` of the factor requested 4674 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4675 4676 Level: developer 4677 4678 Note: 4679 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4680 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4681 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4682 4683 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4684 `MatInitializePackage()` 4685 @*/ 4686 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4687 { 4688 MatSolverTypeHolder next = MatSolverTypeHolders; 4689 PetscBool flg; 4690 MatSolverTypeForSpecifcType inext; 4691 4692 PetscFunctionBegin; 4693 if (foundtype) *foundtype = PETSC_FALSE; 4694 if (foundmtype) *foundmtype = PETSC_FALSE; 4695 if (createfactor) *createfactor = NULL; 4696 4697 if (type) { 4698 while (next) { 4699 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4700 if (flg) { 4701 if (foundtype) *foundtype = PETSC_TRUE; 4702 inext = next->handlers; 4703 while (inext) { 4704 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4705 if (flg) { 4706 if (foundmtype) *foundmtype = PETSC_TRUE; 4707 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4708 PetscFunctionReturn(PETSC_SUCCESS); 4709 } 4710 inext = inext->next; 4711 } 4712 } 4713 next = next->next; 4714 } 4715 } else { 4716 while (next) { 4717 inext = next->handlers; 4718 while (inext) { 4719 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4720 if (flg && inext->createfactor[(int)ftype - 1]) { 4721 if (foundtype) *foundtype = PETSC_TRUE; 4722 if (foundmtype) *foundmtype = PETSC_TRUE; 4723 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4724 PetscFunctionReturn(PETSC_SUCCESS); 4725 } 4726 inext = inext->next; 4727 } 4728 next = next->next; 4729 } 4730 /* try with base classes inext->mtype */ 4731 next = MatSolverTypeHolders; 4732 while (next) { 4733 inext = next->handlers; 4734 while (inext) { 4735 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4736 if (flg && inext->createfactor[(int)ftype - 1]) { 4737 if (foundtype) *foundtype = PETSC_TRUE; 4738 if (foundmtype) *foundmtype = PETSC_TRUE; 4739 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4740 PetscFunctionReturn(PETSC_SUCCESS); 4741 } 4742 inext = inext->next; 4743 } 4744 next = next->next; 4745 } 4746 } 4747 PetscFunctionReturn(PETSC_SUCCESS); 4748 } 4749 4750 PetscErrorCode MatSolverTypeDestroy(void) 4751 { 4752 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4753 MatSolverTypeForSpecifcType inext, iprev; 4754 4755 PetscFunctionBegin; 4756 while (next) { 4757 PetscCall(PetscFree(next->name)); 4758 inext = next->handlers; 4759 while (inext) { 4760 PetscCall(PetscFree(inext->mtype)); 4761 iprev = inext; 4762 inext = inext->next; 4763 PetscCall(PetscFree(iprev)); 4764 } 4765 prev = next; 4766 next = next->next; 4767 PetscCall(PetscFree(prev)); 4768 } 4769 MatSolverTypeHolders = NULL; 4770 PetscFunctionReturn(PETSC_SUCCESS); 4771 } 4772 4773 /*@ 4774 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4775 4776 Logically Collective 4777 4778 Input Parameter: 4779 . mat - the matrix 4780 4781 Output Parameter: 4782 . flg - `PETSC_TRUE` if uses the ordering 4783 4784 Level: developer 4785 4786 Note: 4787 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4788 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4789 4790 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4791 @*/ 4792 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4793 { 4794 PetscFunctionBegin; 4795 *flg = mat->canuseordering; 4796 PetscFunctionReturn(PETSC_SUCCESS); 4797 } 4798 4799 /*@ 4800 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4801 4802 Logically Collective 4803 4804 Input Parameters: 4805 + mat - the matrix obtained with `MatGetFactor()` 4806 - ftype - the factorization type to be used 4807 4808 Output Parameter: 4809 . otype - the preferred ordering type 4810 4811 Level: developer 4812 4813 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4814 @*/ 4815 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4816 { 4817 PetscFunctionBegin; 4818 *otype = mat->preferredordering[ftype]; 4819 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4820 PetscFunctionReturn(PETSC_SUCCESS); 4821 } 4822 4823 /*@ 4824 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4825 4826 Collective 4827 4828 Input Parameters: 4829 + mat - the matrix 4830 . 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 4831 the other criteria is returned 4832 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4833 4834 Output Parameter: 4835 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4836 4837 Options Database Keys: 4838 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4839 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4840 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4841 4842 Level: intermediate 4843 4844 Notes: 4845 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4846 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4847 4848 Users usually access the factorization solvers via `KSP` 4849 4850 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4851 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 4852 4853 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4854 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4855 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4856 4857 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4858 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4859 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4860 4861 Developer Note: 4862 This should actually be called `MatCreateFactor()` since it creates a new factor object 4863 4864 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4865 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4866 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4867 @*/ 4868 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4869 { 4870 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4871 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4872 4873 PetscFunctionBegin; 4874 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4875 PetscValidType(mat, 1); 4876 4877 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4878 MatCheckPreallocated(mat, 1); 4879 4880 PetscCall(MatIsShell(mat, &shell)); 4881 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4882 if (hasop) { 4883 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4884 PetscFunctionReturn(PETSC_SUCCESS); 4885 } 4886 4887 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4888 if (!foundtype) { 4889 if (type) { 4890 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], 4891 ((PetscObject)mat)->type_name, type); 4892 } else { 4893 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); 4894 } 4895 } 4896 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4897 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); 4898 4899 PetscCall((*conv)(mat, ftype, f)); 4900 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4901 PetscFunctionReturn(PETSC_SUCCESS); 4902 } 4903 4904 /*@ 4905 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4906 4907 Not Collective 4908 4909 Input Parameters: 4910 + mat - the matrix 4911 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4912 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4913 4914 Output Parameter: 4915 . flg - PETSC_TRUE if the factorization is available 4916 4917 Level: intermediate 4918 4919 Notes: 4920 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4921 such as pastix, superlu, mumps etc. 4922 4923 PETSc must have been ./configure to use the external solver, using the option --download-package 4924 4925 Developer Note: 4926 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4927 4928 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4929 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4930 @*/ 4931 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4932 { 4933 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4934 4935 PetscFunctionBegin; 4936 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4937 PetscAssertPointer(flg, 4); 4938 4939 *flg = PETSC_FALSE; 4940 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4941 4942 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4943 MatCheckPreallocated(mat, 1); 4944 4945 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4946 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4947 PetscFunctionReturn(PETSC_SUCCESS); 4948 } 4949 4950 /*@ 4951 MatDuplicate - Duplicates a matrix including the non-zero structure. 4952 4953 Collective 4954 4955 Input Parameters: 4956 + mat - the matrix 4957 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4958 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4959 4960 Output Parameter: 4961 . M - pointer to place new matrix 4962 4963 Level: intermediate 4964 4965 Notes: 4966 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4967 4968 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4969 4970 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. 4971 4972 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4973 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4974 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4975 4976 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4977 @*/ 4978 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4979 { 4980 Mat B; 4981 VecType vtype; 4982 PetscInt i; 4983 PetscObject dm, container_h, container_d; 4984 void (*viewf)(void); 4985 4986 PetscFunctionBegin; 4987 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4988 PetscValidType(mat, 1); 4989 PetscAssertPointer(M, 3); 4990 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4991 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4992 MatCheckPreallocated(mat, 1); 4993 4994 *M = NULL; 4995 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4996 PetscUseTypeMethod(mat, duplicate, op, M); 4997 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4998 B = *M; 4999 5000 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 5001 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 5002 PetscCall(MatGetVecType(mat, &vtype)); 5003 PetscCall(MatSetVecType(B, vtype)); 5004 5005 B->stencil.dim = mat->stencil.dim; 5006 B->stencil.noc = mat->stencil.noc; 5007 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 5008 B->stencil.dims[i] = mat->stencil.dims[i]; 5009 B->stencil.starts[i] = mat->stencil.starts[i]; 5010 } 5011 5012 B->nooffproczerorows = mat->nooffproczerorows; 5013 B->nooffprocentries = mat->nooffprocentries; 5014 5015 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5016 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5017 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5018 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5019 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5020 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5021 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5022 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5023 PetscFunctionReturn(PETSC_SUCCESS); 5024 } 5025 5026 /*@ 5027 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5028 5029 Logically Collective 5030 5031 Input Parameter: 5032 . mat - the matrix 5033 5034 Output Parameter: 5035 . v - the diagonal of the matrix 5036 5037 Level: intermediate 5038 5039 Note: 5040 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5041 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5042 is larger than `ndiag`, the values of the remaining entries are unspecified. 5043 5044 Currently only correct in parallel for square matrices. 5045 5046 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5047 @*/ 5048 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5049 { 5050 PetscFunctionBegin; 5051 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5052 PetscValidType(mat, 1); 5053 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5054 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5055 MatCheckPreallocated(mat, 1); 5056 if (PetscDefined(USE_DEBUG)) { 5057 PetscInt nv, row, col, ndiag; 5058 5059 PetscCall(VecGetLocalSize(v, &nv)); 5060 PetscCall(MatGetLocalSize(mat, &row, &col)); 5061 ndiag = PetscMin(row, col); 5062 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); 5063 } 5064 5065 PetscUseTypeMethod(mat, getdiagonal, v); 5066 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5067 PetscFunctionReturn(PETSC_SUCCESS); 5068 } 5069 5070 /*@ 5071 MatGetRowMin - Gets the minimum value (of the real part) of each 5072 row of the matrix 5073 5074 Logically Collective 5075 5076 Input Parameter: 5077 . mat - the matrix 5078 5079 Output Parameters: 5080 + v - the vector for storing the maximums 5081 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5082 5083 Level: intermediate 5084 5085 Note: 5086 The result of this call are the same as if one converted the matrix to dense format 5087 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5088 5089 This code is only implemented for a couple of matrix formats. 5090 5091 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5092 `MatGetRowMax()` 5093 @*/ 5094 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5095 { 5096 PetscFunctionBegin; 5097 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5098 PetscValidType(mat, 1); 5099 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5100 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5101 5102 if (!mat->cmap->N) { 5103 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5104 if (idx) { 5105 PetscInt i, m = mat->rmap->n; 5106 for (i = 0; i < m; i++) idx[i] = -1; 5107 } 5108 } else { 5109 MatCheckPreallocated(mat, 1); 5110 } 5111 PetscUseTypeMethod(mat, getrowmin, v, idx); 5112 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5113 PetscFunctionReturn(PETSC_SUCCESS); 5114 } 5115 5116 /*@ 5117 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5118 row of the matrix 5119 5120 Logically Collective 5121 5122 Input Parameter: 5123 . mat - the matrix 5124 5125 Output Parameters: 5126 + v - the vector for storing the minimums 5127 - idx - the indices of the column found for each row (or `NULL` if not needed) 5128 5129 Level: intermediate 5130 5131 Notes: 5132 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5133 row is 0 (the first column). 5134 5135 This code is only implemented for a couple of matrix formats. 5136 5137 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5138 @*/ 5139 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5140 { 5141 PetscFunctionBegin; 5142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5143 PetscValidType(mat, 1); 5144 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5145 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5146 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5147 5148 if (!mat->cmap->N) { 5149 PetscCall(VecSet(v, 0.0)); 5150 if (idx) { 5151 PetscInt i, m = mat->rmap->n; 5152 for (i = 0; i < m; i++) idx[i] = -1; 5153 } 5154 } else { 5155 MatCheckPreallocated(mat, 1); 5156 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5157 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5158 } 5159 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5160 PetscFunctionReturn(PETSC_SUCCESS); 5161 } 5162 5163 /*@ 5164 MatGetRowMax - Gets the maximum value (of the real part) of each 5165 row of the matrix 5166 5167 Logically Collective 5168 5169 Input Parameter: 5170 . mat - the matrix 5171 5172 Output Parameters: 5173 + v - the vector for storing the maximums 5174 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5175 5176 Level: intermediate 5177 5178 Notes: 5179 The result of this call are the same as if one converted the matrix to dense format 5180 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5181 5182 This code is only implemented for a couple of matrix formats. 5183 5184 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5185 @*/ 5186 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5187 { 5188 PetscFunctionBegin; 5189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5190 PetscValidType(mat, 1); 5191 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5192 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5193 5194 if (!mat->cmap->N) { 5195 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5196 if (idx) { 5197 PetscInt i, m = mat->rmap->n; 5198 for (i = 0; i < m; i++) idx[i] = -1; 5199 } 5200 } else { 5201 MatCheckPreallocated(mat, 1); 5202 PetscUseTypeMethod(mat, getrowmax, v, idx); 5203 } 5204 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5205 PetscFunctionReturn(PETSC_SUCCESS); 5206 } 5207 5208 /*@ 5209 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5210 row of the matrix 5211 5212 Logically Collective 5213 5214 Input Parameter: 5215 . mat - the matrix 5216 5217 Output Parameters: 5218 + v - the vector for storing the maximums 5219 - idx - the indices of the column found for each row (or `NULL` if not needed) 5220 5221 Level: intermediate 5222 5223 Notes: 5224 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5225 row is 0 (the first column). 5226 5227 This code is only implemented for a couple of matrix formats. 5228 5229 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5230 @*/ 5231 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5232 { 5233 PetscFunctionBegin; 5234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5235 PetscValidType(mat, 1); 5236 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5237 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5238 5239 if (!mat->cmap->N) { 5240 PetscCall(VecSet(v, 0.0)); 5241 if (idx) { 5242 PetscInt i, m = mat->rmap->n; 5243 for (i = 0; i < m; i++) idx[i] = -1; 5244 } 5245 } else { 5246 MatCheckPreallocated(mat, 1); 5247 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5248 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5249 } 5250 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5251 PetscFunctionReturn(PETSC_SUCCESS); 5252 } 5253 5254 /*@ 5255 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5256 5257 Logically Collective 5258 5259 Input Parameter: 5260 . mat - the matrix 5261 5262 Output Parameter: 5263 . v - the vector for storing the sum 5264 5265 Level: intermediate 5266 5267 This code is only implemented for a couple of matrix formats. 5268 5269 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5270 @*/ 5271 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5272 { 5273 PetscFunctionBegin; 5274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5275 PetscValidType(mat, 1); 5276 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5277 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5278 5279 if (!mat->cmap->N) { 5280 PetscCall(VecSet(v, 0.0)); 5281 } else { 5282 MatCheckPreallocated(mat, 1); 5283 PetscUseTypeMethod(mat, getrowsumabs, v); 5284 } 5285 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5286 PetscFunctionReturn(PETSC_SUCCESS); 5287 } 5288 5289 /*@ 5290 MatGetRowSum - Gets the sum of each row of the matrix 5291 5292 Logically or Neighborhood Collective 5293 5294 Input Parameter: 5295 . mat - the matrix 5296 5297 Output Parameter: 5298 . v - the vector for storing the sum of rows 5299 5300 Level: intermediate 5301 5302 Note: 5303 This code is slow since it is not currently specialized for different formats 5304 5305 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5306 @*/ 5307 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5308 { 5309 Vec ones; 5310 5311 PetscFunctionBegin; 5312 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5313 PetscValidType(mat, 1); 5314 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5315 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5316 MatCheckPreallocated(mat, 1); 5317 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5318 PetscCall(VecSet(ones, 1.)); 5319 PetscCall(MatMult(mat, ones, v)); 5320 PetscCall(VecDestroy(&ones)); 5321 PetscFunctionReturn(PETSC_SUCCESS); 5322 } 5323 5324 /*@ 5325 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5326 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5327 5328 Collective 5329 5330 Input Parameter: 5331 . mat - the matrix to provide the transpose 5332 5333 Output Parameter: 5334 . 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 5335 5336 Level: advanced 5337 5338 Note: 5339 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 5340 routine allows bypassing that call. 5341 5342 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5343 @*/ 5344 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5345 { 5346 MatParentState *rb = NULL; 5347 5348 PetscFunctionBegin; 5349 PetscCall(PetscNew(&rb)); 5350 rb->id = ((PetscObject)mat)->id; 5351 rb->state = 0; 5352 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5353 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5354 PetscFunctionReturn(PETSC_SUCCESS); 5355 } 5356 5357 /*@ 5358 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5359 5360 Collective 5361 5362 Input Parameters: 5363 + mat - the matrix to transpose 5364 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5365 5366 Output Parameter: 5367 . B - the transpose 5368 5369 Level: intermediate 5370 5371 Notes: 5372 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5373 5374 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the 5375 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5376 5377 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. 5378 5379 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5380 5381 If mat is unchanged from the last call this function returns immediately without recomputing the result 5382 5383 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5384 5385 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5386 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5387 @*/ 5388 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5389 { 5390 PetscContainer rB = NULL; 5391 MatParentState *rb = NULL; 5392 5393 PetscFunctionBegin; 5394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5395 PetscValidType(mat, 1); 5396 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5397 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5398 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5399 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5400 MatCheckPreallocated(mat, 1); 5401 if (reuse == MAT_REUSE_MATRIX) { 5402 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5403 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5404 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5405 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5406 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5407 } 5408 5409 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5410 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5411 PetscUseTypeMethod(mat, transpose, reuse, B); 5412 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5413 } 5414 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5415 5416 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5417 if (reuse != MAT_INPLACE_MATRIX) { 5418 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5419 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5420 rb->state = ((PetscObject)mat)->state; 5421 rb->nonzerostate = mat->nonzerostate; 5422 } 5423 PetscFunctionReturn(PETSC_SUCCESS); 5424 } 5425 5426 /*@ 5427 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5428 5429 Collective 5430 5431 Input Parameter: 5432 . A - the matrix to transpose 5433 5434 Output Parameter: 5435 . 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 5436 numerical portion. 5437 5438 Level: intermediate 5439 5440 Note: 5441 This is not supported for many matrix types, use `MatTranspose()` in those cases 5442 5443 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5444 @*/ 5445 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5446 { 5447 PetscFunctionBegin; 5448 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5449 PetscValidType(A, 1); 5450 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5451 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5452 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5453 PetscUseTypeMethod(A, transposesymbolic, B); 5454 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5455 5456 PetscCall(MatTransposeSetPrecursor(A, *B)); 5457 PetscFunctionReturn(PETSC_SUCCESS); 5458 } 5459 5460 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5461 { 5462 PetscContainer rB; 5463 MatParentState *rb; 5464 5465 PetscFunctionBegin; 5466 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5467 PetscValidType(A, 1); 5468 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5469 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5470 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5471 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5472 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5473 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5474 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5475 PetscFunctionReturn(PETSC_SUCCESS); 5476 } 5477 5478 /*@ 5479 MatIsTranspose - Test whether a matrix is another one's transpose, 5480 or its own, in which case it tests symmetry. 5481 5482 Collective 5483 5484 Input Parameters: 5485 + A - the matrix to test 5486 . B - the matrix to test against, this can equal the first parameter 5487 - tol - tolerance, differences between entries smaller than this are counted as zero 5488 5489 Output Parameter: 5490 . flg - the result 5491 5492 Level: intermediate 5493 5494 Notes: 5495 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5496 test involves parallel copies of the block off-diagonal parts of the matrix. 5497 5498 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5499 @*/ 5500 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5501 { 5502 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5503 5504 PetscFunctionBegin; 5505 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5506 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5507 PetscAssertPointer(flg, 4); 5508 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5509 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5510 *flg = PETSC_FALSE; 5511 if (f && g) { 5512 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5513 PetscCall((*f)(A, B, tol, flg)); 5514 } else { 5515 MatType mattype; 5516 5517 PetscCall(MatGetType(f ? B : A, &mattype)); 5518 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5519 } 5520 PetscFunctionReturn(PETSC_SUCCESS); 5521 } 5522 5523 /*@ 5524 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5525 5526 Collective 5527 5528 Input Parameters: 5529 + mat - the matrix to transpose and complex conjugate 5530 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5531 5532 Output Parameter: 5533 . B - the Hermitian transpose 5534 5535 Level: intermediate 5536 5537 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5538 @*/ 5539 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5540 { 5541 PetscFunctionBegin; 5542 PetscCall(MatTranspose(mat, reuse, B)); 5543 #if defined(PETSC_USE_COMPLEX) 5544 PetscCall(MatConjugate(*B)); 5545 #endif 5546 PetscFunctionReturn(PETSC_SUCCESS); 5547 } 5548 5549 /*@ 5550 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5551 5552 Collective 5553 5554 Input Parameters: 5555 + A - the matrix to test 5556 . B - the matrix to test against, this can equal the first parameter 5557 - tol - tolerance, differences between entries smaller than this are counted as zero 5558 5559 Output Parameter: 5560 . flg - the result 5561 5562 Level: intermediate 5563 5564 Notes: 5565 Only available for `MATAIJ` matrices. 5566 5567 The sequential algorithm 5568 has a running time of the order of the number of nonzeros; the parallel 5569 test involves parallel copies of the block off-diagonal parts of the matrix. 5570 5571 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5572 @*/ 5573 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5574 { 5575 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5576 5577 PetscFunctionBegin; 5578 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5579 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5580 PetscAssertPointer(flg, 4); 5581 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5582 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5583 if (f && g) { 5584 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5585 PetscCall((*f)(A, B, tol, flg)); 5586 } 5587 PetscFunctionReturn(PETSC_SUCCESS); 5588 } 5589 5590 /*@ 5591 MatPermute - Creates a new matrix with rows and columns permuted from the 5592 original. 5593 5594 Collective 5595 5596 Input Parameters: 5597 + mat - the matrix to permute 5598 . row - row permutation, each processor supplies only the permutation for its rows 5599 - col - column permutation, each processor supplies only the permutation for its columns 5600 5601 Output Parameter: 5602 . B - the permuted matrix 5603 5604 Level: advanced 5605 5606 Note: 5607 The index sets map from row/col of permuted matrix to row/col of original matrix. 5608 The index sets should be on the same communicator as mat and have the same local sizes. 5609 5610 Developer Note: 5611 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5612 exploit the fact that row and col are permutations, consider implementing the 5613 more general `MatCreateSubMatrix()` instead. 5614 5615 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5616 @*/ 5617 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5618 { 5619 PetscFunctionBegin; 5620 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5621 PetscValidType(mat, 1); 5622 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5623 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5624 PetscAssertPointer(B, 4); 5625 PetscCheckSameComm(mat, 1, row, 2); 5626 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5627 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5628 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5629 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5630 MatCheckPreallocated(mat, 1); 5631 5632 if (mat->ops->permute) { 5633 PetscUseTypeMethod(mat, permute, row, col, B); 5634 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5635 } else { 5636 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5637 } 5638 PetscFunctionReturn(PETSC_SUCCESS); 5639 } 5640 5641 /*@ 5642 MatEqual - Compares two matrices. 5643 5644 Collective 5645 5646 Input Parameters: 5647 + A - the first matrix 5648 - B - the second matrix 5649 5650 Output Parameter: 5651 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5652 5653 Level: intermediate 5654 5655 .seealso: [](ch_matrices), `Mat` 5656 @*/ 5657 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5658 { 5659 PetscFunctionBegin; 5660 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5661 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5662 PetscValidType(A, 1); 5663 PetscValidType(B, 2); 5664 PetscAssertPointer(flg, 3); 5665 PetscCheckSameComm(A, 1, B, 2); 5666 MatCheckPreallocated(A, 1); 5667 MatCheckPreallocated(B, 2); 5668 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5669 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5670 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, 5671 B->cmap->N); 5672 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5673 PetscUseTypeMethod(A, equal, B, flg); 5674 } else { 5675 PetscCall(MatMultEqual(A, B, 10, flg)); 5676 } 5677 PetscFunctionReturn(PETSC_SUCCESS); 5678 } 5679 5680 /*@ 5681 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5682 matrices that are stored as vectors. Either of the two scaling 5683 matrices can be `NULL`. 5684 5685 Collective 5686 5687 Input Parameters: 5688 + mat - the matrix to be scaled 5689 . l - the left scaling vector (or `NULL`) 5690 - r - the right scaling vector (or `NULL`) 5691 5692 Level: intermediate 5693 5694 Note: 5695 `MatDiagonalScale()` computes $A = LAR$, where 5696 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5697 The L scales the rows of the matrix, the R scales the columns of the matrix. 5698 5699 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5700 @*/ 5701 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5702 { 5703 PetscFunctionBegin; 5704 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5705 PetscValidType(mat, 1); 5706 if (l) { 5707 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5708 PetscCheckSameComm(mat, 1, l, 2); 5709 } 5710 if (r) { 5711 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5712 PetscCheckSameComm(mat, 1, r, 3); 5713 } 5714 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5715 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5716 MatCheckPreallocated(mat, 1); 5717 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5718 5719 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5720 PetscUseTypeMethod(mat, diagonalscale, l, r); 5721 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5722 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5723 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5724 PetscFunctionReturn(PETSC_SUCCESS); 5725 } 5726 5727 /*@ 5728 MatScale - Scales all elements of a matrix by a given number. 5729 5730 Logically Collective 5731 5732 Input Parameters: 5733 + mat - the matrix to be scaled 5734 - a - the scaling value 5735 5736 Level: intermediate 5737 5738 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5739 @*/ 5740 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5741 { 5742 PetscFunctionBegin; 5743 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5744 PetscValidType(mat, 1); 5745 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5746 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5747 PetscValidLogicalCollectiveScalar(mat, a, 2); 5748 MatCheckPreallocated(mat, 1); 5749 5750 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5751 if (a != (PetscScalar)1.0) { 5752 PetscUseTypeMethod(mat, scale, a); 5753 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5754 } 5755 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5756 PetscFunctionReturn(PETSC_SUCCESS); 5757 } 5758 5759 /*@ 5760 MatNorm - Calculates various norms of a matrix. 5761 5762 Collective 5763 5764 Input Parameters: 5765 + mat - the matrix 5766 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5767 5768 Output Parameter: 5769 . nrm - the resulting norm 5770 5771 Level: intermediate 5772 5773 .seealso: [](ch_matrices), `Mat` 5774 @*/ 5775 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5776 { 5777 PetscFunctionBegin; 5778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5779 PetscValidType(mat, 1); 5780 PetscAssertPointer(nrm, 3); 5781 5782 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5783 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5784 MatCheckPreallocated(mat, 1); 5785 5786 PetscUseTypeMethod(mat, norm, type, nrm); 5787 PetscFunctionReturn(PETSC_SUCCESS); 5788 } 5789 5790 /* 5791 This variable is used to prevent counting of MatAssemblyBegin() that 5792 are called from within a MatAssemblyEnd(). 5793 */ 5794 static PetscInt MatAssemblyEnd_InUse = 0; 5795 /*@ 5796 MatAssemblyBegin - Begins assembling the matrix. This routine should 5797 be called after completing all calls to `MatSetValues()`. 5798 5799 Collective 5800 5801 Input Parameters: 5802 + mat - the matrix 5803 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5804 5805 Level: beginner 5806 5807 Notes: 5808 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5809 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5810 5811 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5812 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5813 using the matrix. 5814 5815 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5816 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 5817 a global collective operation requiring all processes that share the matrix. 5818 5819 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5820 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5821 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5822 5823 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5824 @*/ 5825 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5826 { 5827 PetscFunctionBegin; 5828 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5829 PetscValidType(mat, 1); 5830 MatCheckPreallocated(mat, 1); 5831 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5832 if (mat->assembled) { 5833 mat->was_assembled = PETSC_TRUE; 5834 mat->assembled = PETSC_FALSE; 5835 } 5836 5837 if (!MatAssemblyEnd_InUse) { 5838 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5839 PetscTryTypeMethod(mat, assemblybegin, type); 5840 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5841 } else PetscTryTypeMethod(mat, assemblybegin, type); 5842 PetscFunctionReturn(PETSC_SUCCESS); 5843 } 5844 5845 /*@ 5846 MatAssembled - Indicates if a matrix has been assembled and is ready for 5847 use; for example, in matrix-vector product. 5848 5849 Not Collective 5850 5851 Input Parameter: 5852 . mat - the matrix 5853 5854 Output Parameter: 5855 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5856 5857 Level: advanced 5858 5859 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5860 @*/ 5861 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5862 { 5863 PetscFunctionBegin; 5864 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5865 PetscAssertPointer(assembled, 2); 5866 *assembled = mat->assembled; 5867 PetscFunctionReturn(PETSC_SUCCESS); 5868 } 5869 5870 /*@ 5871 MatAssemblyEnd - Completes assembling the matrix. This routine should 5872 be called after `MatAssemblyBegin()`. 5873 5874 Collective 5875 5876 Input Parameters: 5877 + mat - the matrix 5878 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5879 5880 Options Database Keys: 5881 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5882 . -mat_view ::ascii_info_detail - Prints more detailed info 5883 . -mat_view - Prints matrix in ASCII format 5884 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5885 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5886 . -display <name> - Sets display name (default is host) 5887 . -draw_pause <sec> - Sets number of seconds to pause after display 5888 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5889 . -viewer_socket_machine <machine> - Machine to use for socket 5890 . -viewer_socket_port <port> - Port number to use for socket 5891 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5892 5893 Level: beginner 5894 5895 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5896 @*/ 5897 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5898 { 5899 static PetscInt inassm = 0; 5900 PetscBool flg = PETSC_FALSE; 5901 5902 PetscFunctionBegin; 5903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5904 PetscValidType(mat, 1); 5905 5906 inassm++; 5907 MatAssemblyEnd_InUse++; 5908 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5909 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5910 PetscTryTypeMethod(mat, assemblyend, type); 5911 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5912 } else PetscTryTypeMethod(mat, assemblyend, type); 5913 5914 /* Flush assembly is not a true assembly */ 5915 if (type != MAT_FLUSH_ASSEMBLY) { 5916 if (mat->num_ass) { 5917 if (!mat->symmetry_eternal) { 5918 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5919 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5920 } 5921 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5922 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5923 } 5924 mat->num_ass++; 5925 mat->assembled = PETSC_TRUE; 5926 mat->ass_nonzerostate = mat->nonzerostate; 5927 } 5928 5929 mat->insertmode = NOT_SET_VALUES; 5930 MatAssemblyEnd_InUse--; 5931 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5932 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5933 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5934 5935 if (mat->checksymmetryonassembly) { 5936 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5937 if (flg) { 5938 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5939 } else { 5940 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5941 } 5942 } 5943 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5944 } 5945 inassm--; 5946 PetscFunctionReturn(PETSC_SUCCESS); 5947 } 5948 5949 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5950 /*@ 5951 MatSetOption - Sets a parameter option for a matrix. Some options 5952 may be specific to certain storage formats. Some options 5953 determine how values will be inserted (or added). Sorted, 5954 row-oriented input will generally assemble the fastest. The default 5955 is row-oriented. 5956 5957 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5958 5959 Input Parameters: 5960 + mat - the matrix 5961 . op - the option, one of those listed below (and possibly others), 5962 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5963 5964 Options Describing Matrix Structure: 5965 + `MAT_SPD` - symmetric positive definite 5966 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5967 . `MAT_HERMITIAN` - transpose is the complex conjugation 5968 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5969 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5970 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5971 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5972 5973 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5974 do not need to be computed (usually at a high cost) 5975 5976 Options For Use with `MatSetValues()`: 5977 Insert a logically dense subblock, which can be 5978 . `MAT_ROW_ORIENTED` - row-oriented (default) 5979 5980 These options reflect the data you pass in with `MatSetValues()`; it has 5981 nothing to do with how the data is stored internally in the matrix 5982 data structure. 5983 5984 When (re)assembling a matrix, we can restrict the input for 5985 efficiency/debugging purposes. These options include 5986 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5987 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5988 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5989 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5990 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5991 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5992 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5993 performance for very large process counts. 5994 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5995 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5996 functions, instead sending only neighbor messages. 5997 5998 Level: intermediate 5999 6000 Notes: 6001 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 6002 6003 Some options are relevant only for particular matrix types and 6004 are thus ignored by others. Other options are not supported by 6005 certain matrix types and will generate an error message if set. 6006 6007 If using Fortran to compute a matrix, one may need to 6008 use the column-oriented option (or convert to the row-oriented 6009 format). 6010 6011 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6012 that would generate a new entry in the nonzero structure is instead 6013 ignored. Thus, if memory has not already been allocated for this particular 6014 data, then the insertion is ignored. For dense matrices, in which 6015 the entire array is allocated, no entries are ever ignored. 6016 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6017 6018 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6019 that would generate a new entry in the nonzero structure instead produces 6020 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 6021 6022 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6023 that would generate a new entry that has not been preallocated will 6024 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6025 only.) This is a useful flag when debugging matrix memory preallocation. 6026 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6027 6028 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6029 other processors should be dropped, rather than stashed. 6030 This is useful if you know that the "owning" processor is also 6031 always generating the correct matrix entries, so that PETSc need 6032 not transfer duplicate entries generated on another processor. 6033 6034 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6035 searches during matrix assembly. When this flag is set, the hash table 6036 is created during the first matrix assembly. This hash table is 6037 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6038 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6039 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6040 supported by `MATMPIBAIJ` format only. 6041 6042 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6043 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6044 6045 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6046 a zero location in the matrix 6047 6048 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6049 6050 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6051 zero row routines and thus improves performance for very large process counts. 6052 6053 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6054 part of the matrix (since they should match the upper triangular part). 6055 6056 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6057 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6058 with finite difference schemes with non-periodic boundary conditions. 6059 6060 Developer Note: 6061 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6062 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6063 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6064 not changed. 6065 6066 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6067 @*/ 6068 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6069 { 6070 PetscFunctionBegin; 6071 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6072 if (op > 0) { 6073 PetscValidLogicalCollectiveEnum(mat, op, 2); 6074 PetscValidLogicalCollectiveBool(mat, flg, 3); 6075 } 6076 6077 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); 6078 6079 switch (op) { 6080 case MAT_FORCE_DIAGONAL_ENTRIES: 6081 mat->force_diagonals = flg; 6082 PetscFunctionReturn(PETSC_SUCCESS); 6083 case MAT_NO_OFF_PROC_ENTRIES: 6084 mat->nooffprocentries = flg; 6085 PetscFunctionReturn(PETSC_SUCCESS); 6086 case MAT_SUBSET_OFF_PROC_ENTRIES: 6087 mat->assembly_subset = flg; 6088 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6089 #if !defined(PETSC_HAVE_MPIUNI) 6090 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6091 #endif 6092 mat->stash.first_assembly_done = PETSC_FALSE; 6093 } 6094 PetscFunctionReturn(PETSC_SUCCESS); 6095 case MAT_NO_OFF_PROC_ZERO_ROWS: 6096 mat->nooffproczerorows = flg; 6097 PetscFunctionReturn(PETSC_SUCCESS); 6098 case MAT_SPD: 6099 if (flg) { 6100 mat->spd = PETSC_BOOL3_TRUE; 6101 mat->symmetric = PETSC_BOOL3_TRUE; 6102 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6103 } else { 6104 mat->spd = PETSC_BOOL3_FALSE; 6105 } 6106 break; 6107 case MAT_SYMMETRIC: 6108 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6109 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6110 #if !defined(PETSC_USE_COMPLEX) 6111 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6112 #endif 6113 break; 6114 case MAT_HERMITIAN: 6115 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6116 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6117 #if !defined(PETSC_USE_COMPLEX) 6118 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6119 #endif 6120 break; 6121 case MAT_STRUCTURALLY_SYMMETRIC: 6122 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6123 break; 6124 case MAT_SYMMETRY_ETERNAL: 6125 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"); 6126 mat->symmetry_eternal = flg; 6127 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6128 break; 6129 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6130 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"); 6131 mat->structural_symmetry_eternal = flg; 6132 break; 6133 case MAT_SPD_ETERNAL: 6134 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"); 6135 mat->spd_eternal = flg; 6136 if (flg) { 6137 mat->structural_symmetry_eternal = PETSC_TRUE; 6138 mat->symmetry_eternal = PETSC_TRUE; 6139 } 6140 break; 6141 case MAT_STRUCTURE_ONLY: 6142 mat->structure_only = flg; 6143 break; 6144 case MAT_SORTED_FULL: 6145 mat->sortedfull = flg; 6146 break; 6147 default: 6148 break; 6149 } 6150 PetscTryTypeMethod(mat, setoption, op, flg); 6151 PetscFunctionReturn(PETSC_SUCCESS); 6152 } 6153 6154 /*@ 6155 MatGetOption - Gets a parameter option that has been set for a matrix. 6156 6157 Logically Collective 6158 6159 Input Parameters: 6160 + mat - the matrix 6161 - op - the option, this only responds to certain options, check the code for which ones 6162 6163 Output Parameter: 6164 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6165 6166 Level: intermediate 6167 6168 Notes: 6169 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6170 6171 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6172 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6173 6174 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6175 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6176 @*/ 6177 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6178 { 6179 PetscFunctionBegin; 6180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6181 PetscValidType(mat, 1); 6182 6183 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); 6184 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()"); 6185 6186 switch (op) { 6187 case MAT_NO_OFF_PROC_ENTRIES: 6188 *flg = mat->nooffprocentries; 6189 break; 6190 case MAT_NO_OFF_PROC_ZERO_ROWS: 6191 *flg = mat->nooffproczerorows; 6192 break; 6193 case MAT_SYMMETRIC: 6194 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6195 break; 6196 case MAT_HERMITIAN: 6197 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6198 break; 6199 case MAT_STRUCTURALLY_SYMMETRIC: 6200 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6201 break; 6202 case MAT_SPD: 6203 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6204 break; 6205 case MAT_SYMMETRY_ETERNAL: 6206 *flg = mat->symmetry_eternal; 6207 break; 6208 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6209 *flg = mat->symmetry_eternal; 6210 break; 6211 default: 6212 break; 6213 } 6214 PetscFunctionReturn(PETSC_SUCCESS); 6215 } 6216 6217 /*@ 6218 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6219 this routine retains the old nonzero structure. 6220 6221 Logically Collective 6222 6223 Input Parameter: 6224 . mat - the matrix 6225 6226 Level: intermediate 6227 6228 Note: 6229 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. 6230 See the Performance chapter of the users manual for information on preallocating matrices. 6231 6232 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6233 @*/ 6234 PetscErrorCode MatZeroEntries(Mat mat) 6235 { 6236 PetscFunctionBegin; 6237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6238 PetscValidType(mat, 1); 6239 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6240 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"); 6241 MatCheckPreallocated(mat, 1); 6242 6243 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6244 PetscUseTypeMethod(mat, zeroentries); 6245 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6246 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6247 PetscFunctionReturn(PETSC_SUCCESS); 6248 } 6249 6250 /*@ 6251 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6252 of a set of rows and columns of a matrix. 6253 6254 Collective 6255 6256 Input Parameters: 6257 + mat - the matrix 6258 . numRows - the number of rows/columns to zero 6259 . rows - the global row indices 6260 . diag - value put in the diagonal of the eliminated rows 6261 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6262 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6263 6264 Level: intermediate 6265 6266 Notes: 6267 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6268 6269 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6270 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 6271 6272 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6273 Krylov method to take advantage of the known solution on the zeroed rows. 6274 6275 For the parallel case, all processes that share the matrix (i.e., 6276 those in the communicator used for matrix creation) MUST call this 6277 routine, regardless of whether any rows being zeroed are owned by 6278 them. 6279 6280 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6281 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 6282 missing. 6283 6284 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6285 list only rows local to itself). 6286 6287 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6288 6289 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6290 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6291 @*/ 6292 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6293 { 6294 PetscFunctionBegin; 6295 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6296 PetscValidType(mat, 1); 6297 if (numRows) PetscAssertPointer(rows, 3); 6298 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6299 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6300 MatCheckPreallocated(mat, 1); 6301 6302 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6303 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6304 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6305 PetscFunctionReturn(PETSC_SUCCESS); 6306 } 6307 6308 /*@ 6309 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6310 of a set of rows and columns of a matrix. 6311 6312 Collective 6313 6314 Input Parameters: 6315 + mat - the matrix 6316 . is - the rows to zero 6317 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6318 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6319 - b - optional vector of right-hand side, that will be adjusted by provided solution 6320 6321 Level: intermediate 6322 6323 Note: 6324 See `MatZeroRowsColumns()` for details on how this routine operates. 6325 6326 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6327 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6328 @*/ 6329 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6330 { 6331 PetscInt numRows; 6332 const PetscInt *rows; 6333 6334 PetscFunctionBegin; 6335 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6336 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6337 PetscValidType(mat, 1); 6338 PetscValidType(is, 2); 6339 PetscCall(ISGetLocalSize(is, &numRows)); 6340 PetscCall(ISGetIndices(is, &rows)); 6341 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6342 PetscCall(ISRestoreIndices(is, &rows)); 6343 PetscFunctionReturn(PETSC_SUCCESS); 6344 } 6345 6346 /*@ 6347 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6348 of a set of rows of a matrix. 6349 6350 Collective 6351 6352 Input Parameters: 6353 + mat - the matrix 6354 . numRows - the number of rows to zero 6355 . rows - the global row indices 6356 . diag - value put in the diagonal of the zeroed rows 6357 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6358 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6359 6360 Level: intermediate 6361 6362 Notes: 6363 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6364 6365 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6366 6367 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6368 Krylov method to take advantage of the known solution on the zeroed rows. 6369 6370 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) 6371 from the matrix. 6372 6373 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6374 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal 6375 formats this does not alter the nonzero structure. 6376 6377 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6378 of the matrix is not changed the values are 6379 merely zeroed. 6380 6381 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6382 formats can optionally remove the main diagonal entry from the 6383 nonzero structure as well, by passing 0.0 as the final argument). 6384 6385 For the parallel case, all processes that share the matrix (i.e., 6386 those in the communicator used for matrix creation) MUST call this 6387 routine, regardless of whether any rows being zeroed are owned by 6388 them. 6389 6390 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6391 list only rows local to itself). 6392 6393 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6394 owns that are to be zeroed. This saves a global synchronization in the implementation. 6395 6396 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6397 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6398 @*/ 6399 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6400 { 6401 PetscFunctionBegin; 6402 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6403 PetscValidType(mat, 1); 6404 if (numRows) PetscAssertPointer(rows, 3); 6405 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6406 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6407 MatCheckPreallocated(mat, 1); 6408 6409 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6410 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6411 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6412 PetscFunctionReturn(PETSC_SUCCESS); 6413 } 6414 6415 /*@ 6416 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6417 of a set of rows of a matrix. 6418 6419 Collective 6420 6421 Input Parameters: 6422 + mat - the matrix 6423 . is - index set of rows to remove (if `NULL` then no row is removed) 6424 . diag - value put in all diagonals of eliminated rows 6425 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6426 - b - optional vector of right-hand side, that will be adjusted by provided solution 6427 6428 Level: intermediate 6429 6430 Note: 6431 See `MatZeroRows()` for details on how this routine operates. 6432 6433 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6434 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6435 @*/ 6436 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6437 { 6438 PetscInt numRows = 0; 6439 const PetscInt *rows = NULL; 6440 6441 PetscFunctionBegin; 6442 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6443 PetscValidType(mat, 1); 6444 if (is) { 6445 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6446 PetscCall(ISGetLocalSize(is, &numRows)); 6447 PetscCall(ISGetIndices(is, &rows)); 6448 } 6449 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6450 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6451 PetscFunctionReturn(PETSC_SUCCESS); 6452 } 6453 6454 /*@ 6455 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6456 of a set of rows of a matrix. These rows must be local to the process. 6457 6458 Collective 6459 6460 Input Parameters: 6461 + mat - the matrix 6462 . numRows - the number of rows to remove 6463 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6464 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6465 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6466 - b - optional vector of right-hand side, that will be adjusted by provided solution 6467 6468 Level: intermediate 6469 6470 Notes: 6471 See `MatZeroRows()` for details on how this routine operates. 6472 6473 The grid coordinates are across the entire grid, not just the local portion 6474 6475 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6476 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6477 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6478 `DM_BOUNDARY_PERIODIC` boundary type. 6479 6480 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 6481 a single value per point) you can skip filling those indices. 6482 6483 Fortran Note: 6484 `idxm` and `idxn` should be declared as 6485 $ MatStencil idxm(4, m) 6486 and the values inserted using 6487 .vb 6488 idxm(MatStencil_i, 1) = i 6489 idxm(MatStencil_j, 1) = j 6490 idxm(MatStencil_k, 1) = k 6491 idxm(MatStencil_c, 1) = c 6492 etc 6493 .ve 6494 6495 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6496 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6497 @*/ 6498 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6499 { 6500 PetscInt dim = mat->stencil.dim; 6501 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6502 PetscInt *dims = mat->stencil.dims + 1; 6503 PetscInt *starts = mat->stencil.starts; 6504 PetscInt *dxm = (PetscInt *)rows; 6505 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6506 6507 PetscFunctionBegin; 6508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6509 PetscValidType(mat, 1); 6510 if (numRows) PetscAssertPointer(rows, 3); 6511 6512 PetscCall(PetscMalloc1(numRows, &jdxm)); 6513 for (i = 0; i < numRows; ++i) { 6514 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6515 for (j = 0; j < 3 - sdim; ++j) dxm++; 6516 /* Local index in X dir */ 6517 tmp = *dxm++ - starts[0]; 6518 /* Loop over remaining dimensions */ 6519 for (j = 0; j < dim - 1; ++j) { 6520 /* If nonlocal, set index to be negative */ 6521 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6522 /* Update local index */ 6523 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6524 } 6525 /* Skip component slot if necessary */ 6526 if (mat->stencil.noc) dxm++; 6527 /* Local row number */ 6528 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6529 } 6530 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6531 PetscCall(PetscFree(jdxm)); 6532 PetscFunctionReturn(PETSC_SUCCESS); 6533 } 6534 6535 /*@ 6536 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6537 of a set of rows and columns of a matrix. 6538 6539 Collective 6540 6541 Input Parameters: 6542 + mat - the matrix 6543 . numRows - the number of rows/columns to remove 6544 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6545 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6546 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6547 - b - optional vector of right-hand side, that will be adjusted by provided solution 6548 6549 Level: intermediate 6550 6551 Notes: 6552 See `MatZeroRowsColumns()` for details on how this routine operates. 6553 6554 The grid coordinates are across the entire grid, not just the local portion 6555 6556 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6557 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6558 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6559 `DM_BOUNDARY_PERIODIC` boundary type. 6560 6561 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 6562 a single value per point) you can skip filling those indices. 6563 6564 Fortran Note: 6565 `idxm` and `idxn` should be declared as 6566 $ MatStencil idxm(4, m) 6567 and the values inserted using 6568 .vb 6569 idxm(MatStencil_i, 1) = i 6570 idxm(MatStencil_j, 1) = j 6571 idxm(MatStencil_k, 1) = k 6572 idxm(MatStencil_c, 1) = c 6573 etc 6574 .ve 6575 6576 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6577 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6578 @*/ 6579 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6580 { 6581 PetscInt dim = mat->stencil.dim; 6582 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6583 PetscInt *dims = mat->stencil.dims + 1; 6584 PetscInt *starts = mat->stencil.starts; 6585 PetscInt *dxm = (PetscInt *)rows; 6586 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6587 6588 PetscFunctionBegin; 6589 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6590 PetscValidType(mat, 1); 6591 if (numRows) PetscAssertPointer(rows, 3); 6592 6593 PetscCall(PetscMalloc1(numRows, &jdxm)); 6594 for (i = 0; i < numRows; ++i) { 6595 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6596 for (j = 0; j < 3 - sdim; ++j) dxm++; 6597 /* Local index in X dir */ 6598 tmp = *dxm++ - starts[0]; 6599 /* Loop over remaining dimensions */ 6600 for (j = 0; j < dim - 1; ++j) { 6601 /* If nonlocal, set index to be negative */ 6602 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6603 /* Update local index */ 6604 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6605 } 6606 /* Skip component slot if necessary */ 6607 if (mat->stencil.noc) dxm++; 6608 /* Local row number */ 6609 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6610 } 6611 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6612 PetscCall(PetscFree(jdxm)); 6613 PetscFunctionReturn(PETSC_SUCCESS); 6614 } 6615 6616 /*@ 6617 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6618 of a set of rows of a matrix; using local numbering of rows. 6619 6620 Collective 6621 6622 Input Parameters: 6623 + mat - the matrix 6624 . numRows - the number of rows to remove 6625 . rows - the local row indices 6626 . diag - value put in all diagonals of eliminated rows 6627 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6628 - b - optional vector of right-hand side, that will be adjusted by provided solution 6629 6630 Level: intermediate 6631 6632 Notes: 6633 Before calling `MatZeroRowsLocal()`, the user must first set the 6634 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6635 6636 See `MatZeroRows()` for details on how this routine operates. 6637 6638 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6639 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6640 @*/ 6641 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6642 { 6643 PetscFunctionBegin; 6644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6645 PetscValidType(mat, 1); 6646 if (numRows) PetscAssertPointer(rows, 3); 6647 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6648 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6649 MatCheckPreallocated(mat, 1); 6650 6651 if (mat->ops->zerorowslocal) { 6652 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6653 } else { 6654 IS is, newis; 6655 const PetscInt *newRows; 6656 6657 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6658 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6659 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6660 PetscCall(ISGetIndices(newis, &newRows)); 6661 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6662 PetscCall(ISRestoreIndices(newis, &newRows)); 6663 PetscCall(ISDestroy(&newis)); 6664 PetscCall(ISDestroy(&is)); 6665 } 6666 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6667 PetscFunctionReturn(PETSC_SUCCESS); 6668 } 6669 6670 /*@ 6671 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6672 of a set of rows of a matrix; using local numbering of rows. 6673 6674 Collective 6675 6676 Input Parameters: 6677 + mat - the matrix 6678 . is - index set of rows to remove 6679 . diag - value put in all diagonals of eliminated rows 6680 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6681 - b - optional vector of right-hand side, that will be adjusted by provided solution 6682 6683 Level: intermediate 6684 6685 Notes: 6686 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6687 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6688 6689 See `MatZeroRows()` for details on how this routine operates. 6690 6691 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6692 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6693 @*/ 6694 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6695 { 6696 PetscInt numRows; 6697 const PetscInt *rows; 6698 6699 PetscFunctionBegin; 6700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6701 PetscValidType(mat, 1); 6702 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6703 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6704 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6705 MatCheckPreallocated(mat, 1); 6706 6707 PetscCall(ISGetLocalSize(is, &numRows)); 6708 PetscCall(ISGetIndices(is, &rows)); 6709 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6710 PetscCall(ISRestoreIndices(is, &rows)); 6711 PetscFunctionReturn(PETSC_SUCCESS); 6712 } 6713 6714 /*@ 6715 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6716 of a set of rows and columns of a matrix; using local numbering of rows. 6717 6718 Collective 6719 6720 Input Parameters: 6721 + mat - the matrix 6722 . numRows - the number of rows to remove 6723 . rows - the global row indices 6724 . diag - value put in all diagonals of eliminated rows 6725 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6726 - b - optional vector of right-hand side, that will be adjusted by provided solution 6727 6728 Level: intermediate 6729 6730 Notes: 6731 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6732 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6733 6734 See `MatZeroRowsColumns()` for details on how this routine operates. 6735 6736 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6737 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6738 @*/ 6739 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6740 { 6741 IS is, newis; 6742 const PetscInt *newRows; 6743 6744 PetscFunctionBegin; 6745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6746 PetscValidType(mat, 1); 6747 if (numRows) PetscAssertPointer(rows, 3); 6748 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6749 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6750 MatCheckPreallocated(mat, 1); 6751 6752 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6753 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6754 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6755 PetscCall(ISGetIndices(newis, &newRows)); 6756 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6757 PetscCall(ISRestoreIndices(newis, &newRows)); 6758 PetscCall(ISDestroy(&newis)); 6759 PetscCall(ISDestroy(&is)); 6760 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6761 PetscFunctionReturn(PETSC_SUCCESS); 6762 } 6763 6764 /*@ 6765 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6766 of a set of rows and columns of a matrix; using local numbering of rows. 6767 6768 Collective 6769 6770 Input Parameters: 6771 + mat - the matrix 6772 . is - index set of rows to remove 6773 . diag - value put in all diagonals of eliminated rows 6774 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6775 - b - optional vector of right-hand side, that will be adjusted by provided solution 6776 6777 Level: intermediate 6778 6779 Notes: 6780 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6781 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6782 6783 See `MatZeroRowsColumns()` for details on how this routine operates. 6784 6785 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6786 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6787 @*/ 6788 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6789 { 6790 PetscInt numRows; 6791 const PetscInt *rows; 6792 6793 PetscFunctionBegin; 6794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6795 PetscValidType(mat, 1); 6796 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6797 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6799 MatCheckPreallocated(mat, 1); 6800 6801 PetscCall(ISGetLocalSize(is, &numRows)); 6802 PetscCall(ISGetIndices(is, &rows)); 6803 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6804 PetscCall(ISRestoreIndices(is, &rows)); 6805 PetscFunctionReturn(PETSC_SUCCESS); 6806 } 6807 6808 /*@ 6809 MatGetSize - Returns the numbers of rows and columns in a matrix. 6810 6811 Not Collective 6812 6813 Input Parameter: 6814 . mat - the matrix 6815 6816 Output Parameters: 6817 + m - the number of global rows 6818 - n - the number of global columns 6819 6820 Level: beginner 6821 6822 Note: 6823 Both output parameters can be `NULL` on input. 6824 6825 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6826 @*/ 6827 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6828 { 6829 PetscFunctionBegin; 6830 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6831 if (m) *m = mat->rmap->N; 6832 if (n) *n = mat->cmap->N; 6833 PetscFunctionReturn(PETSC_SUCCESS); 6834 } 6835 6836 /*@ 6837 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6838 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6839 6840 Not Collective 6841 6842 Input Parameter: 6843 . mat - the matrix 6844 6845 Output Parameters: 6846 + m - the number of local rows, use `NULL` to not obtain this value 6847 - n - the number of local columns, use `NULL` to not obtain this value 6848 6849 Level: beginner 6850 6851 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6852 @*/ 6853 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6854 { 6855 PetscFunctionBegin; 6856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6857 if (m) PetscAssertPointer(m, 2); 6858 if (n) PetscAssertPointer(n, 3); 6859 if (m) *m = mat->rmap->n; 6860 if (n) *n = mat->cmap->n; 6861 PetscFunctionReturn(PETSC_SUCCESS); 6862 } 6863 6864 /*@ 6865 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6866 vector one multiplies this matrix by that are owned by this processor. 6867 6868 Not Collective, unless matrix has not been allocated, then collective 6869 6870 Input Parameter: 6871 . mat - the matrix 6872 6873 Output Parameters: 6874 + m - the global index of the first local column, use `NULL` to not obtain this value 6875 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6876 6877 Level: developer 6878 6879 Notes: 6880 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6881 6882 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6883 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6884 6885 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6886 the local values in the matrix. 6887 6888 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6889 Layouts](sec_matlayout) for details on matrix layouts. 6890 6891 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6892 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6893 @*/ 6894 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6895 { 6896 PetscFunctionBegin; 6897 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6898 PetscValidType(mat, 1); 6899 if (m) PetscAssertPointer(m, 2); 6900 if (n) PetscAssertPointer(n, 3); 6901 MatCheckPreallocated(mat, 1); 6902 if (m) *m = mat->cmap->rstart; 6903 if (n) *n = mat->cmap->rend; 6904 PetscFunctionReturn(PETSC_SUCCESS); 6905 } 6906 6907 /*@ 6908 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6909 this MPI process. 6910 6911 Not Collective 6912 6913 Input Parameter: 6914 . mat - the matrix 6915 6916 Output Parameters: 6917 + m - the global index of the first local row, use `NULL` to not obtain this value 6918 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6919 6920 Level: beginner 6921 6922 Notes: 6923 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6924 6925 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6926 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6927 6928 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6929 the local values in the matrix. 6930 6931 The high argument is one more than the last element stored locally. 6932 6933 For all matrices it returns the range of matrix rows associated with rows of a vector that 6934 would contain the result of a matrix vector product with this matrix. See [Matrix 6935 Layouts](sec_matlayout) for details on matrix layouts. 6936 6937 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6938 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6939 @*/ 6940 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6941 { 6942 PetscFunctionBegin; 6943 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6944 PetscValidType(mat, 1); 6945 if (m) PetscAssertPointer(m, 2); 6946 if (n) PetscAssertPointer(n, 3); 6947 MatCheckPreallocated(mat, 1); 6948 if (m) *m = mat->rmap->rstart; 6949 if (n) *n = mat->rmap->rend; 6950 PetscFunctionReturn(PETSC_SUCCESS); 6951 } 6952 6953 /*@C 6954 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6955 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6956 6957 Not Collective, unless matrix has not been allocated 6958 6959 Input Parameter: 6960 . mat - the matrix 6961 6962 Output Parameter: 6963 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6964 where `size` is the number of MPI processes used by `mat` 6965 6966 Level: beginner 6967 6968 Notes: 6969 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6970 6971 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6972 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6973 6974 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6975 the local values in the matrix. 6976 6977 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6978 would contain the result of a matrix vector product with this matrix. See [Matrix 6979 Layouts](sec_matlayout) for details on matrix layouts. 6980 6981 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6982 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6983 `DMDAGetGhostCorners()`, `DM` 6984 @*/ 6985 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6986 { 6987 PetscFunctionBegin; 6988 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6989 PetscValidType(mat, 1); 6990 MatCheckPreallocated(mat, 1); 6991 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6992 PetscFunctionReturn(PETSC_SUCCESS); 6993 } 6994 6995 /*@C 6996 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6997 vector one multiplies this vector by that are owned by each processor. 6998 6999 Not Collective, unless matrix has not been allocated 7000 7001 Input Parameter: 7002 . mat - the matrix 7003 7004 Output Parameter: 7005 . ranges - start of each processors portion plus one more than the total length at the end 7006 7007 Level: beginner 7008 7009 Notes: 7010 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7011 7012 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7013 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7014 7015 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7016 the local values in the matrix. 7017 7018 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7019 Layouts](sec_matlayout) for details on matrix layouts. 7020 7021 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7022 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7023 `DMDAGetGhostCorners()`, `DM` 7024 @*/ 7025 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7026 { 7027 PetscFunctionBegin; 7028 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7029 PetscValidType(mat, 1); 7030 MatCheckPreallocated(mat, 1); 7031 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7032 PetscFunctionReturn(PETSC_SUCCESS); 7033 } 7034 7035 /*@ 7036 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7037 7038 Not Collective 7039 7040 Input Parameter: 7041 . A - matrix 7042 7043 Output Parameters: 7044 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7045 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7046 7047 Level: intermediate 7048 7049 Note: 7050 You should call `ISDestroy()` on the returned `IS` 7051 7052 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7053 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7054 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7055 details on matrix layouts. 7056 7057 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7058 @*/ 7059 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7060 { 7061 PetscErrorCode (*f)(Mat, IS *, IS *); 7062 7063 PetscFunctionBegin; 7064 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7065 PetscValidType(A, 1); 7066 MatCheckPreallocated(A, 1); 7067 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7068 if (f) { 7069 PetscCall((*f)(A, rows, cols)); 7070 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7071 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7072 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7073 } 7074 PetscFunctionReturn(PETSC_SUCCESS); 7075 } 7076 7077 /*@ 7078 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7079 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7080 to complete the factorization. 7081 7082 Collective 7083 7084 Input Parameters: 7085 + fact - the factorized matrix obtained with `MatGetFactor()` 7086 . mat - the matrix 7087 . row - row permutation 7088 . col - column permutation 7089 - info - structure containing 7090 .vb 7091 levels - number of levels of fill. 7092 expected fill - as ratio of original fill. 7093 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7094 missing diagonal entries) 7095 .ve 7096 7097 Level: developer 7098 7099 Notes: 7100 See [Matrix Factorization](sec_matfactor) for additional information. 7101 7102 Most users should employ the `KSP` interface for linear solvers 7103 instead of working directly with matrix algebra routines such as this. 7104 See, e.g., `KSPCreate()`. 7105 7106 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7107 7108 Developer Note: 7109 The Fortran interface is not autogenerated as the 7110 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7111 7112 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7113 `MatGetOrdering()`, `MatFactorInfo` 7114 @*/ 7115 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7116 { 7117 PetscFunctionBegin; 7118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7119 PetscValidType(mat, 2); 7120 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7121 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7122 PetscAssertPointer(info, 5); 7123 PetscAssertPointer(fact, 1); 7124 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7125 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7127 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7128 MatCheckPreallocated(mat, 2); 7129 7130 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7131 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7132 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7133 PetscFunctionReturn(PETSC_SUCCESS); 7134 } 7135 7136 /*@ 7137 MatICCFactorSymbolic - Performs symbolic incomplete 7138 Cholesky factorization for a symmetric matrix. Use 7139 `MatCholeskyFactorNumeric()` to complete the factorization. 7140 7141 Collective 7142 7143 Input Parameters: 7144 + fact - the factorized matrix obtained with `MatGetFactor()` 7145 . mat - the matrix to be factored 7146 . perm - row and column permutation 7147 - info - structure containing 7148 .vb 7149 levels - number of levels of fill. 7150 expected fill - as ratio of original fill. 7151 .ve 7152 7153 Level: developer 7154 7155 Notes: 7156 Most users should employ the `KSP` interface for linear solvers 7157 instead of working directly with matrix algebra routines such as this. 7158 See, e.g., `KSPCreate()`. 7159 7160 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7161 7162 Developer Note: 7163 The Fortran interface is not autogenerated as the 7164 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7165 7166 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7167 @*/ 7168 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7169 { 7170 PetscFunctionBegin; 7171 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7172 PetscValidType(mat, 2); 7173 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7174 PetscAssertPointer(info, 4); 7175 PetscAssertPointer(fact, 1); 7176 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7177 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7178 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7179 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7180 MatCheckPreallocated(mat, 2); 7181 7182 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7183 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7184 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7185 PetscFunctionReturn(PETSC_SUCCESS); 7186 } 7187 7188 /*@C 7189 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7190 points to an array of valid matrices, they may be reused to store the new 7191 submatrices. 7192 7193 Collective 7194 7195 Input Parameters: 7196 + mat - the matrix 7197 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7198 . irow - index set of rows to extract 7199 . icol - index set of columns to extract 7200 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7201 7202 Output Parameter: 7203 . submat - the array of submatrices 7204 7205 Level: advanced 7206 7207 Notes: 7208 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7209 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7210 to extract a parallel submatrix. 7211 7212 Some matrix types place restrictions on the row and column 7213 indices, such as that they be sorted or that they be equal to each other. 7214 7215 The index sets may not have duplicate entries. 7216 7217 When extracting submatrices from a parallel matrix, each processor can 7218 form a different submatrix by setting the rows and columns of its 7219 individual index sets according to the local submatrix desired. 7220 7221 When finished using the submatrices, the user should destroy 7222 them with `MatDestroySubMatrices()`. 7223 7224 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7225 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7226 7227 This routine creates the matrices in submat; you should NOT create them before 7228 calling it. It also allocates the array of matrix pointers submat. 7229 7230 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7231 request one row/column in a block, they must request all rows/columns that are in 7232 that block. For example, if the block size is 2 you cannot request just row 0 and 7233 column 0. 7234 7235 Fortran Note: 7236 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7237 7238 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7239 @*/ 7240 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7241 { 7242 PetscInt i; 7243 PetscBool eq; 7244 7245 PetscFunctionBegin; 7246 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7247 PetscValidType(mat, 1); 7248 if (n) { 7249 PetscAssertPointer(irow, 3); 7250 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7251 PetscAssertPointer(icol, 4); 7252 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7253 } 7254 PetscAssertPointer(submat, 6); 7255 if (n && scall == MAT_REUSE_MATRIX) { 7256 PetscAssertPointer(*submat, 6); 7257 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7258 } 7259 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7260 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7261 MatCheckPreallocated(mat, 1); 7262 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7263 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7264 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7265 for (i = 0; i < n; i++) { 7266 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7267 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7268 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7269 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7270 if (mat->boundtocpu && mat->bindingpropagates) { 7271 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7272 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7273 } 7274 #endif 7275 } 7276 PetscFunctionReturn(PETSC_SUCCESS); 7277 } 7278 7279 /*@C 7280 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7281 7282 Collective 7283 7284 Input Parameters: 7285 + mat - the matrix 7286 . n - the number of submatrixes to be extracted 7287 . irow - index set of rows to extract 7288 . icol - index set of columns to extract 7289 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7290 7291 Output Parameter: 7292 . submat - the array of submatrices 7293 7294 Level: advanced 7295 7296 Note: 7297 This is used by `PCGASM` 7298 7299 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7300 @*/ 7301 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7302 { 7303 PetscInt i; 7304 PetscBool eq; 7305 7306 PetscFunctionBegin; 7307 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7308 PetscValidType(mat, 1); 7309 if (n) { 7310 PetscAssertPointer(irow, 3); 7311 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7312 PetscAssertPointer(icol, 4); 7313 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7314 } 7315 PetscAssertPointer(submat, 6); 7316 if (n && scall == MAT_REUSE_MATRIX) { 7317 PetscAssertPointer(*submat, 6); 7318 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7319 } 7320 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7321 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7322 MatCheckPreallocated(mat, 1); 7323 7324 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7325 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7326 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7327 for (i = 0; i < n; i++) { 7328 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7329 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7330 } 7331 PetscFunctionReturn(PETSC_SUCCESS); 7332 } 7333 7334 /*@C 7335 MatDestroyMatrices - Destroys an array of matrices. 7336 7337 Collective 7338 7339 Input Parameters: 7340 + n - the number of local matrices 7341 - mat - the matrices (this is a pointer to the array of matrices) 7342 7343 Level: advanced 7344 7345 Notes: 7346 Frees not only the matrices, but also the array that contains the matrices 7347 7348 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7349 7350 Fortran Note: 7351 Does not free the `mat` array. 7352 7353 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7354 @*/ 7355 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7356 { 7357 PetscInt i; 7358 7359 PetscFunctionBegin; 7360 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7361 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7362 PetscAssertPointer(mat, 2); 7363 7364 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7365 7366 /* memory is allocated even if n = 0 */ 7367 PetscCall(PetscFree(*mat)); 7368 PetscFunctionReturn(PETSC_SUCCESS); 7369 } 7370 7371 /*@C 7372 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7373 7374 Collective 7375 7376 Input Parameters: 7377 + n - the number of local matrices 7378 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7379 sequence of `MatCreateSubMatrices()`) 7380 7381 Level: advanced 7382 7383 Note: 7384 Frees not only the matrices, but also the array that contains the matrices 7385 7386 Fortran Note: 7387 Does not free the `mat` array. 7388 7389 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7390 @*/ 7391 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7392 { 7393 Mat mat0; 7394 7395 PetscFunctionBegin; 7396 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7397 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7398 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7399 PetscAssertPointer(mat, 2); 7400 7401 mat0 = (*mat)[0]; 7402 if (mat0 && mat0->ops->destroysubmatrices) { 7403 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7404 } else { 7405 PetscCall(MatDestroyMatrices(n, mat)); 7406 } 7407 PetscFunctionReturn(PETSC_SUCCESS); 7408 } 7409 7410 /*@ 7411 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7412 7413 Collective 7414 7415 Input Parameter: 7416 . mat - the matrix 7417 7418 Output Parameter: 7419 . matstruct - the sequential matrix with the nonzero structure of `mat` 7420 7421 Level: developer 7422 7423 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7424 @*/ 7425 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7426 { 7427 PetscFunctionBegin; 7428 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7429 PetscAssertPointer(matstruct, 2); 7430 7431 PetscValidType(mat, 1); 7432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7433 MatCheckPreallocated(mat, 1); 7434 7435 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7436 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7437 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7438 PetscFunctionReturn(PETSC_SUCCESS); 7439 } 7440 7441 /*@C 7442 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7443 7444 Collective 7445 7446 Input Parameter: 7447 . mat - the matrix 7448 7449 Level: advanced 7450 7451 Note: 7452 This is not needed, one can just call `MatDestroy()` 7453 7454 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7455 @*/ 7456 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7457 { 7458 PetscFunctionBegin; 7459 PetscAssertPointer(mat, 1); 7460 PetscCall(MatDestroy(mat)); 7461 PetscFunctionReturn(PETSC_SUCCESS); 7462 } 7463 7464 /*@ 7465 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7466 replaces the index sets by larger ones that represent submatrices with 7467 additional overlap. 7468 7469 Collective 7470 7471 Input Parameters: 7472 + mat - the matrix 7473 . n - the number of index sets 7474 . is - the array of index sets (these index sets will changed during the call) 7475 - ov - the additional overlap requested 7476 7477 Options Database Key: 7478 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7479 7480 Level: developer 7481 7482 Note: 7483 The computed overlap preserves the matrix block sizes when the blocks are square. 7484 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7485 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7486 7487 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7488 @*/ 7489 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7490 { 7491 PetscInt i, bs, cbs; 7492 7493 PetscFunctionBegin; 7494 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7495 PetscValidType(mat, 1); 7496 PetscValidLogicalCollectiveInt(mat, n, 2); 7497 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7498 if (n) { 7499 PetscAssertPointer(is, 3); 7500 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7501 } 7502 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7503 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7504 MatCheckPreallocated(mat, 1); 7505 7506 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7507 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7508 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7509 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7510 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7511 if (bs == cbs) { 7512 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7513 } 7514 PetscFunctionReturn(PETSC_SUCCESS); 7515 } 7516 7517 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7518 7519 /*@ 7520 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7521 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7522 additional overlap. 7523 7524 Collective 7525 7526 Input Parameters: 7527 + mat - the matrix 7528 . n - the number of index sets 7529 . is - the array of index sets (these index sets will changed during the call) 7530 - ov - the additional overlap requested 7531 7532 ` Options Database Key: 7533 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7534 7535 Level: developer 7536 7537 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7538 @*/ 7539 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7540 { 7541 PetscInt i; 7542 7543 PetscFunctionBegin; 7544 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7545 PetscValidType(mat, 1); 7546 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7547 if (n) { 7548 PetscAssertPointer(is, 3); 7549 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7550 } 7551 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7552 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7553 MatCheckPreallocated(mat, 1); 7554 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7555 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7556 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7557 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7558 PetscFunctionReturn(PETSC_SUCCESS); 7559 } 7560 7561 /*@ 7562 MatGetBlockSize - Returns the matrix block size. 7563 7564 Not Collective 7565 7566 Input Parameter: 7567 . mat - the matrix 7568 7569 Output Parameter: 7570 . bs - block size 7571 7572 Level: intermediate 7573 7574 Notes: 7575 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7576 7577 If the block size has not been set yet this routine returns 1. 7578 7579 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7580 @*/ 7581 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7582 { 7583 PetscFunctionBegin; 7584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7585 PetscAssertPointer(bs, 2); 7586 *bs = PetscAbs(mat->rmap->bs); 7587 PetscFunctionReturn(PETSC_SUCCESS); 7588 } 7589 7590 /*@ 7591 MatGetBlockSizes - Returns the matrix block row and column sizes. 7592 7593 Not Collective 7594 7595 Input Parameter: 7596 . mat - the matrix 7597 7598 Output Parameters: 7599 + rbs - row block size 7600 - cbs - column block size 7601 7602 Level: intermediate 7603 7604 Notes: 7605 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7606 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7607 7608 If a block size has not been set yet this routine returns 1. 7609 7610 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7611 @*/ 7612 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7613 { 7614 PetscFunctionBegin; 7615 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7616 if (rbs) PetscAssertPointer(rbs, 2); 7617 if (cbs) PetscAssertPointer(cbs, 3); 7618 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7619 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7620 PetscFunctionReturn(PETSC_SUCCESS); 7621 } 7622 7623 /*@ 7624 MatSetBlockSize - Sets the matrix block size. 7625 7626 Logically Collective 7627 7628 Input Parameters: 7629 + mat - the matrix 7630 - bs - block size 7631 7632 Level: intermediate 7633 7634 Notes: 7635 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7636 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7637 7638 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7639 is compatible with the matrix local sizes. 7640 7641 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7642 @*/ 7643 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7644 { 7645 PetscFunctionBegin; 7646 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7647 PetscValidLogicalCollectiveInt(mat, bs, 2); 7648 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7649 PetscFunctionReturn(PETSC_SUCCESS); 7650 } 7651 7652 typedef struct { 7653 PetscInt n; 7654 IS *is; 7655 Mat *mat; 7656 PetscObjectState nonzerostate; 7657 Mat C; 7658 } EnvelopeData; 7659 7660 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7661 { 7662 EnvelopeData *edata = (EnvelopeData *)*ptr; 7663 7664 PetscFunctionBegin; 7665 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7666 PetscCall(PetscFree(edata->is)); 7667 PetscCall(PetscFree(edata)); 7668 PetscFunctionReturn(PETSC_SUCCESS); 7669 } 7670 7671 /*@ 7672 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7673 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7674 7675 Collective 7676 7677 Input Parameter: 7678 . mat - the matrix 7679 7680 Level: intermediate 7681 7682 Notes: 7683 There can be zeros within the blocks 7684 7685 The blocks can overlap between processes, including laying on more than two processes 7686 7687 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7688 @*/ 7689 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7690 { 7691 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7692 PetscInt *diag, *odiag, sc; 7693 VecScatter scatter; 7694 PetscScalar *seqv; 7695 const PetscScalar *parv; 7696 const PetscInt *ia, *ja; 7697 PetscBool set, flag, done; 7698 Mat AA = mat, A; 7699 MPI_Comm comm; 7700 PetscMPIInt rank, size, tag; 7701 MPI_Status status; 7702 PetscContainer container; 7703 EnvelopeData *edata; 7704 Vec seq, par; 7705 IS isglobal; 7706 7707 PetscFunctionBegin; 7708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7709 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7710 if (!set || !flag) { 7711 /* TODO: only needs nonzero structure of transpose */ 7712 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7713 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7714 } 7715 PetscCall(MatAIJGetLocalMat(AA, &A)); 7716 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7717 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7718 7719 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7720 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7721 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7722 PetscCallMPI(MPI_Comm_size(comm, &size)); 7723 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7724 7725 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7726 7727 if (rank > 0) { 7728 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7729 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7730 } 7731 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7732 for (i = 0; i < n; i++) { 7733 env = PetscMax(env, ja[ia[i + 1] - 1]); 7734 II = rstart + i; 7735 if (env == II) { 7736 starts[lblocks] = tbs; 7737 sizes[lblocks++] = 1 + II - tbs; 7738 tbs = 1 + II; 7739 } 7740 } 7741 if (rank < size - 1) { 7742 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7743 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7744 } 7745 7746 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7747 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7748 PetscCall(MatDestroy(&A)); 7749 7750 PetscCall(PetscNew(&edata)); 7751 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7752 edata->n = lblocks; 7753 /* create IS needed for extracting blocks from the original matrix */ 7754 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7755 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7756 7757 /* Create the resulting inverse matrix structure with preallocation information */ 7758 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7759 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7760 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7761 PetscCall(MatSetType(edata->C, MATAIJ)); 7762 7763 /* Communicate the start and end of each row, from each block to the correct rank */ 7764 /* TODO: Use PetscSF instead of VecScatter */ 7765 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7766 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7767 PetscCall(VecGetArrayWrite(seq, &seqv)); 7768 for (PetscInt i = 0; i < lblocks; i++) { 7769 for (PetscInt j = 0; j < sizes[i]; j++) { 7770 seqv[cnt] = starts[i]; 7771 seqv[cnt + 1] = starts[i] + sizes[i]; 7772 cnt += 2; 7773 } 7774 } 7775 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7776 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7777 sc -= cnt; 7778 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7779 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7780 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7781 PetscCall(ISDestroy(&isglobal)); 7782 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7783 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7784 PetscCall(VecScatterDestroy(&scatter)); 7785 PetscCall(VecDestroy(&seq)); 7786 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7787 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7788 PetscCall(VecGetArrayRead(par, &parv)); 7789 cnt = 0; 7790 PetscCall(MatGetSize(mat, NULL, &n)); 7791 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7792 PetscInt start, end, d = 0, od = 0; 7793 7794 start = (PetscInt)PetscRealPart(parv[cnt]); 7795 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7796 cnt += 2; 7797 7798 if (start < cstart) { 7799 od += cstart - start + n - cend; 7800 d += cend - cstart; 7801 } else if (start < cend) { 7802 od += n - cend; 7803 d += cend - start; 7804 } else od += n - start; 7805 if (end <= cstart) { 7806 od -= cstart - end + n - cend; 7807 d -= cend - cstart; 7808 } else if (end < cend) { 7809 od -= n - cend; 7810 d -= cend - end; 7811 } else od -= n - end; 7812 7813 odiag[i] = od; 7814 diag[i] = d; 7815 } 7816 PetscCall(VecRestoreArrayRead(par, &parv)); 7817 PetscCall(VecDestroy(&par)); 7818 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7819 PetscCall(PetscFree2(diag, odiag)); 7820 PetscCall(PetscFree2(sizes, starts)); 7821 7822 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7823 PetscCall(PetscContainerSetPointer(container, edata)); 7824 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7825 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7826 PetscCall(PetscObjectDereference((PetscObject)container)); 7827 PetscFunctionReturn(PETSC_SUCCESS); 7828 } 7829 7830 /*@ 7831 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7832 7833 Collective 7834 7835 Input Parameters: 7836 + A - the matrix 7837 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7838 7839 Output Parameter: 7840 . C - matrix with inverted block diagonal of `A` 7841 7842 Level: advanced 7843 7844 Note: 7845 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7846 7847 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7848 @*/ 7849 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7850 { 7851 PetscContainer container; 7852 EnvelopeData *edata; 7853 PetscObjectState nonzerostate; 7854 7855 PetscFunctionBegin; 7856 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7857 if (!container) { 7858 PetscCall(MatComputeVariableBlockEnvelope(A)); 7859 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7860 } 7861 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7862 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7863 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7864 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7865 7866 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7867 *C = edata->C; 7868 7869 for (PetscInt i = 0; i < edata->n; i++) { 7870 Mat D; 7871 PetscScalar *dvalues; 7872 7873 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7874 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7875 PetscCall(MatSeqDenseInvert(D)); 7876 PetscCall(MatDenseGetArray(D, &dvalues)); 7877 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7878 PetscCall(MatDestroy(&D)); 7879 } 7880 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7881 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7882 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7883 PetscFunctionReturn(PETSC_SUCCESS); 7884 } 7885 7886 /*@ 7887 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7888 7889 Not Collective 7890 7891 Input Parameters: 7892 + mat - the matrix 7893 . nblocks - the number of blocks on this process, each block can only exist on a single process 7894 - bsizes - the block sizes 7895 7896 Level: intermediate 7897 7898 Notes: 7899 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7900 7901 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. 7902 7903 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7904 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7905 @*/ 7906 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7907 { 7908 PetscInt ncnt = 0, nlocal; 7909 7910 PetscFunctionBegin; 7911 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7912 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7913 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); 7914 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7915 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); 7916 PetscCall(PetscFree(mat->bsizes)); 7917 mat->nblocks = nblocks; 7918 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7919 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7920 PetscFunctionReturn(PETSC_SUCCESS); 7921 } 7922 7923 /*@C 7924 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7925 7926 Not Collective; No Fortran Support 7927 7928 Input Parameter: 7929 . mat - the matrix 7930 7931 Output Parameters: 7932 + nblocks - the number of blocks on this process 7933 - bsizes - the block sizes 7934 7935 Level: intermediate 7936 7937 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7938 @*/ 7939 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7940 { 7941 PetscFunctionBegin; 7942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7943 if (nblocks) *nblocks = mat->nblocks; 7944 if (bsizes) *bsizes = mat->bsizes; 7945 PetscFunctionReturn(PETSC_SUCCESS); 7946 } 7947 7948 /*@ 7949 MatSetBlockSizes - Sets the matrix block row and column sizes. 7950 7951 Logically Collective 7952 7953 Input Parameters: 7954 + mat - the matrix 7955 . rbs - row block size 7956 - cbs - column block size 7957 7958 Level: intermediate 7959 7960 Notes: 7961 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7962 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7963 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7964 7965 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7966 are compatible with the matrix local sizes. 7967 7968 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7969 7970 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7971 @*/ 7972 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7973 { 7974 PetscFunctionBegin; 7975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7976 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7977 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7978 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7979 if (mat->rmap->refcnt) { 7980 ISLocalToGlobalMapping l2g = NULL; 7981 PetscLayout nmap = NULL; 7982 7983 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7984 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7985 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7986 mat->rmap = nmap; 7987 mat->rmap->mapping = l2g; 7988 } 7989 if (mat->cmap->refcnt) { 7990 ISLocalToGlobalMapping l2g = NULL; 7991 PetscLayout nmap = NULL; 7992 7993 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7994 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7995 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7996 mat->cmap = nmap; 7997 mat->cmap->mapping = l2g; 7998 } 7999 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8000 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8001 PetscFunctionReturn(PETSC_SUCCESS); 8002 } 8003 8004 /*@ 8005 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8006 8007 Logically Collective 8008 8009 Input Parameters: 8010 + mat - the matrix 8011 . fromRow - matrix from which to copy row block size 8012 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8013 8014 Level: developer 8015 8016 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8017 @*/ 8018 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8019 { 8020 PetscFunctionBegin; 8021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8022 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8023 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8024 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8025 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8026 PetscFunctionReturn(PETSC_SUCCESS); 8027 } 8028 8029 /*@ 8030 MatResidual - Default routine to calculate the residual r = b - Ax 8031 8032 Collective 8033 8034 Input Parameters: 8035 + mat - the matrix 8036 . b - the right-hand-side 8037 - x - the approximate solution 8038 8039 Output Parameter: 8040 . r - location to store the residual 8041 8042 Level: developer 8043 8044 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8045 @*/ 8046 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8047 { 8048 PetscFunctionBegin; 8049 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8050 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8051 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8052 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8053 PetscValidType(mat, 1); 8054 MatCheckPreallocated(mat, 1); 8055 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8056 if (!mat->ops->residual) { 8057 PetscCall(MatMult(mat, x, r)); 8058 PetscCall(VecAYPX(r, -1.0, b)); 8059 } else { 8060 PetscUseTypeMethod(mat, residual, b, x, r); 8061 } 8062 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8063 PetscFunctionReturn(PETSC_SUCCESS); 8064 } 8065 8066 /*MC 8067 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8068 8069 Synopsis: 8070 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8071 8072 Not Collective 8073 8074 Input Parameters: 8075 + A - the matrix 8076 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8077 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8078 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8079 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8080 always used. 8081 8082 Output Parameters: 8083 + n - number of local rows in the (possibly compressed) matrix 8084 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8085 . ja - the column indices 8086 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8087 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8088 8089 Level: developer 8090 8091 Note: 8092 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8093 8094 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8095 M*/ 8096 8097 /*MC 8098 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8099 8100 Synopsis: 8101 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8102 8103 Not Collective 8104 8105 Input Parameters: 8106 + A - the matrix 8107 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8108 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8109 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8110 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8111 always used. 8112 . n - number of local rows in the (possibly compressed) matrix 8113 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8114 . ja - the column indices 8115 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8116 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8117 8118 Level: developer 8119 8120 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8121 M*/ 8122 8123 /*@C 8124 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8125 8126 Collective 8127 8128 Input Parameters: 8129 + mat - the matrix 8130 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8131 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8132 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8133 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8134 always used. 8135 8136 Output Parameters: 8137 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8138 . 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 8139 . ja - the column indices, use `NULL` if not needed 8140 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8141 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8142 8143 Level: developer 8144 8145 Notes: 8146 You CANNOT change any of the ia[] or ja[] values. 8147 8148 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8149 8150 Fortran Notes: 8151 Use 8152 .vb 8153 PetscInt, pointer :: ia(:),ja(:) 8154 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8155 ! Access the ith and jth entries via ia(i) and ja(j) 8156 .ve 8157 8158 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8159 8160 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8161 @*/ 8162 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8163 { 8164 PetscFunctionBegin; 8165 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8166 PetscValidType(mat, 1); 8167 if (n) PetscAssertPointer(n, 5); 8168 if (ia) PetscAssertPointer(ia, 6); 8169 if (ja) PetscAssertPointer(ja, 7); 8170 if (done) PetscAssertPointer(done, 8); 8171 MatCheckPreallocated(mat, 1); 8172 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8173 else { 8174 if (done) *done = PETSC_TRUE; 8175 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8176 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8177 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8178 } 8179 PetscFunctionReturn(PETSC_SUCCESS); 8180 } 8181 8182 /*@C 8183 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8184 8185 Collective 8186 8187 Input Parameters: 8188 + mat - the matrix 8189 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8190 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8191 symmetrized 8192 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8193 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8194 always used. 8195 . n - number of columns in the (possibly compressed) matrix 8196 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8197 - ja - the row indices 8198 8199 Output Parameter: 8200 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8201 8202 Level: developer 8203 8204 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8205 @*/ 8206 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8207 { 8208 PetscFunctionBegin; 8209 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8210 PetscValidType(mat, 1); 8211 PetscAssertPointer(n, 5); 8212 if (ia) PetscAssertPointer(ia, 6); 8213 if (ja) PetscAssertPointer(ja, 7); 8214 PetscAssertPointer(done, 8); 8215 MatCheckPreallocated(mat, 1); 8216 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8217 else { 8218 *done = PETSC_TRUE; 8219 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8220 } 8221 PetscFunctionReturn(PETSC_SUCCESS); 8222 } 8223 8224 /*@C 8225 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8226 8227 Collective 8228 8229 Input Parameters: 8230 + mat - the matrix 8231 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8232 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8233 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8234 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8235 always used. 8236 . n - size of (possibly compressed) matrix 8237 . ia - the row pointers 8238 - ja - the column indices 8239 8240 Output Parameter: 8241 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8242 8243 Level: developer 8244 8245 Note: 8246 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8247 us of the array after it has been restored. If you pass `NULL`, it will 8248 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8249 8250 Fortran Note: 8251 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8252 8253 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8254 @*/ 8255 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8256 { 8257 PetscFunctionBegin; 8258 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8259 PetscValidType(mat, 1); 8260 if (ia) PetscAssertPointer(ia, 6); 8261 if (ja) PetscAssertPointer(ja, 7); 8262 if (done) PetscAssertPointer(done, 8); 8263 MatCheckPreallocated(mat, 1); 8264 8265 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8266 else { 8267 if (done) *done = PETSC_TRUE; 8268 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8269 if (n) *n = 0; 8270 if (ia) *ia = NULL; 8271 if (ja) *ja = NULL; 8272 } 8273 PetscFunctionReturn(PETSC_SUCCESS); 8274 } 8275 8276 /*@C 8277 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8278 8279 Collective 8280 8281 Input Parameters: 8282 + mat - the matrix 8283 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8284 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8285 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8286 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8287 always used. 8288 8289 Output Parameters: 8290 + n - size of (possibly compressed) matrix 8291 . ia - the column pointers 8292 . ja - the row indices 8293 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8294 8295 Level: developer 8296 8297 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8298 @*/ 8299 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8300 { 8301 PetscFunctionBegin; 8302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8303 PetscValidType(mat, 1); 8304 if (ia) PetscAssertPointer(ia, 6); 8305 if (ja) PetscAssertPointer(ja, 7); 8306 PetscAssertPointer(done, 8); 8307 MatCheckPreallocated(mat, 1); 8308 8309 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8310 else { 8311 *done = PETSC_TRUE; 8312 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8313 if (n) *n = 0; 8314 if (ia) *ia = NULL; 8315 if (ja) *ja = NULL; 8316 } 8317 PetscFunctionReturn(PETSC_SUCCESS); 8318 } 8319 8320 /*@ 8321 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8322 `MatGetColumnIJ()`. 8323 8324 Collective 8325 8326 Input Parameters: 8327 + mat - the matrix 8328 . ncolors - maximum color value 8329 . n - number of entries in colorarray 8330 - colorarray - array indicating color for each column 8331 8332 Output Parameter: 8333 . iscoloring - coloring generated using colorarray information 8334 8335 Level: developer 8336 8337 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8338 @*/ 8339 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8340 { 8341 PetscFunctionBegin; 8342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8343 PetscValidType(mat, 1); 8344 PetscAssertPointer(colorarray, 4); 8345 PetscAssertPointer(iscoloring, 5); 8346 MatCheckPreallocated(mat, 1); 8347 8348 if (!mat->ops->coloringpatch) { 8349 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8350 } else { 8351 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8352 } 8353 PetscFunctionReturn(PETSC_SUCCESS); 8354 } 8355 8356 /*@ 8357 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8358 8359 Logically Collective 8360 8361 Input Parameter: 8362 . mat - the factored matrix to be reset 8363 8364 Level: developer 8365 8366 Notes: 8367 This routine should be used only with factored matrices formed by in-place 8368 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8369 format). This option can save memory, for example, when solving nonlinear 8370 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8371 ILU(0) preconditioner. 8372 8373 One can specify in-place ILU(0) factorization by calling 8374 .vb 8375 PCType(pc,PCILU); 8376 PCFactorSeUseInPlace(pc); 8377 .ve 8378 or by using the options -pc_type ilu -pc_factor_in_place 8379 8380 In-place factorization ILU(0) can also be used as a local 8381 solver for the blocks within the block Jacobi or additive Schwarz 8382 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8383 for details on setting local solver options. 8384 8385 Most users should employ the `KSP` interface for linear solvers 8386 instead of working directly with matrix algebra routines such as this. 8387 See, e.g., `KSPCreate()`. 8388 8389 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8390 @*/ 8391 PetscErrorCode MatSetUnfactored(Mat mat) 8392 { 8393 PetscFunctionBegin; 8394 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8395 PetscValidType(mat, 1); 8396 MatCheckPreallocated(mat, 1); 8397 mat->factortype = MAT_FACTOR_NONE; 8398 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8399 PetscUseTypeMethod(mat, setunfactored); 8400 PetscFunctionReturn(PETSC_SUCCESS); 8401 } 8402 8403 /*MC 8404 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8405 8406 Synopsis: 8407 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8408 8409 Not Collective 8410 8411 Input Parameter: 8412 . x - matrix 8413 8414 Output Parameters: 8415 + xx_v - the Fortran pointer to the array 8416 - ierr - error code 8417 8418 Example of Usage: 8419 .vb 8420 PetscScalar, pointer xx_v(:,:) 8421 .... 8422 call MatDenseGetArrayF90(x,xx_v,ierr) 8423 a = xx_v(3) 8424 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8425 .ve 8426 8427 Level: advanced 8428 8429 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8430 M*/ 8431 8432 /*MC 8433 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8434 accessed with `MatDenseGetArrayF90()`. 8435 8436 Synopsis: 8437 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8438 8439 Not Collective 8440 8441 Input Parameters: 8442 + x - matrix 8443 - xx_v - the Fortran90 pointer to the array 8444 8445 Output Parameter: 8446 . ierr - error code 8447 8448 Example of Usage: 8449 .vb 8450 PetscScalar, pointer xx_v(:,:) 8451 .... 8452 call MatDenseGetArrayF90(x,xx_v,ierr) 8453 a = xx_v(3) 8454 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8455 .ve 8456 8457 Level: advanced 8458 8459 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8460 M*/ 8461 8462 /*MC 8463 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8464 8465 Synopsis: 8466 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8467 8468 Not Collective 8469 8470 Input Parameter: 8471 . x - matrix 8472 8473 Output Parameters: 8474 + xx_v - the Fortran pointer to the array 8475 - ierr - error code 8476 8477 Example of Usage: 8478 .vb 8479 PetscScalar, pointer xx_v(:) 8480 .... 8481 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8482 a = xx_v(3) 8483 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8484 .ve 8485 8486 Level: advanced 8487 8488 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8489 M*/ 8490 8491 /*MC 8492 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8493 accessed with `MatSeqAIJGetArrayF90()`. 8494 8495 Synopsis: 8496 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8497 8498 Not Collective 8499 8500 Input Parameters: 8501 + x - matrix 8502 - xx_v - the Fortran90 pointer to the array 8503 8504 Output Parameter: 8505 . ierr - error code 8506 8507 Example of Usage: 8508 .vb 8509 PetscScalar, pointer xx_v(:) 8510 .... 8511 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8512 a = xx_v(3) 8513 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8514 .ve 8515 8516 Level: advanced 8517 8518 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8519 M*/ 8520 8521 /*@ 8522 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8523 as the original matrix. 8524 8525 Collective 8526 8527 Input Parameters: 8528 + mat - the original matrix 8529 . isrow - parallel `IS` containing the rows this processor should obtain 8530 . 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. 8531 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8532 8533 Output Parameter: 8534 . newmat - the new submatrix, of the same type as the original matrix 8535 8536 Level: advanced 8537 8538 Notes: 8539 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8540 8541 Some matrix types place restrictions on the row and column indices, such 8542 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; 8543 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8544 8545 The index sets may not have duplicate entries. 8546 8547 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8548 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8549 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8550 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8551 you are finished using it. 8552 8553 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8554 the input matrix. 8555 8556 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8557 8558 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8559 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8560 8561 Example usage: 8562 Consider the following 8x8 matrix with 34 non-zero values, that is 8563 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8564 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8565 as follows 8566 .vb 8567 1 2 0 | 0 3 0 | 0 4 8568 Proc0 0 5 6 | 7 0 0 | 8 0 8569 9 0 10 | 11 0 0 | 12 0 8570 ------------------------------------- 8571 13 0 14 | 15 16 17 | 0 0 8572 Proc1 0 18 0 | 19 20 21 | 0 0 8573 0 0 0 | 22 23 0 | 24 0 8574 ------------------------------------- 8575 Proc2 25 26 27 | 0 0 28 | 29 0 8576 30 0 0 | 31 32 33 | 0 34 8577 .ve 8578 8579 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8580 8581 .vb 8582 2 0 | 0 3 0 | 0 8583 Proc0 5 6 | 7 0 0 | 8 8584 ------------------------------- 8585 Proc1 18 0 | 19 20 21 | 0 8586 ------------------------------- 8587 Proc2 26 27 | 0 0 28 | 29 8588 0 0 | 31 32 33 | 0 8589 .ve 8590 8591 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8592 @*/ 8593 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8594 { 8595 PetscMPIInt size; 8596 Mat *local; 8597 IS iscoltmp; 8598 PetscBool flg; 8599 8600 PetscFunctionBegin; 8601 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8602 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8603 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8604 PetscAssertPointer(newmat, 5); 8605 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8606 PetscValidType(mat, 1); 8607 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8608 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8609 8610 MatCheckPreallocated(mat, 1); 8611 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8612 8613 if (!iscol || isrow == iscol) { 8614 PetscBool stride; 8615 PetscMPIInt grabentirematrix = 0, grab; 8616 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8617 if (stride) { 8618 PetscInt first, step, n, rstart, rend; 8619 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8620 if (step == 1) { 8621 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8622 if (rstart == first) { 8623 PetscCall(ISGetLocalSize(isrow, &n)); 8624 if (n == rend - rstart) grabentirematrix = 1; 8625 } 8626 } 8627 } 8628 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8629 if (grab) { 8630 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8631 if (cll == MAT_INITIAL_MATRIX) { 8632 *newmat = mat; 8633 PetscCall(PetscObjectReference((PetscObject)mat)); 8634 } 8635 PetscFunctionReturn(PETSC_SUCCESS); 8636 } 8637 } 8638 8639 if (!iscol) { 8640 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8641 } else { 8642 iscoltmp = iscol; 8643 } 8644 8645 /* if original matrix is on just one processor then use submatrix generated */ 8646 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8647 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8648 goto setproperties; 8649 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8650 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8651 *newmat = *local; 8652 PetscCall(PetscFree(local)); 8653 goto setproperties; 8654 } else if (!mat->ops->createsubmatrix) { 8655 /* Create a new matrix type that implements the operation using the full matrix */ 8656 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8657 switch (cll) { 8658 case MAT_INITIAL_MATRIX: 8659 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8660 break; 8661 case MAT_REUSE_MATRIX: 8662 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8663 break; 8664 default: 8665 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8666 } 8667 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8668 goto setproperties; 8669 } 8670 8671 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8672 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8673 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8674 8675 setproperties: 8676 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8677 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8678 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8679 } 8680 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8681 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8682 PetscFunctionReturn(PETSC_SUCCESS); 8683 } 8684 8685 /*@ 8686 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8687 8688 Not Collective 8689 8690 Input Parameters: 8691 + A - the matrix we wish to propagate options from 8692 - B - the matrix we wish to propagate options to 8693 8694 Level: beginner 8695 8696 Note: 8697 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8698 8699 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8700 @*/ 8701 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8702 { 8703 PetscFunctionBegin; 8704 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8705 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8706 B->symmetry_eternal = A->symmetry_eternal; 8707 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8708 B->symmetric = A->symmetric; 8709 B->structurally_symmetric = A->structurally_symmetric; 8710 B->spd = A->spd; 8711 B->hermitian = A->hermitian; 8712 PetscFunctionReturn(PETSC_SUCCESS); 8713 } 8714 8715 /*@ 8716 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8717 used during the assembly process to store values that belong to 8718 other processors. 8719 8720 Not Collective 8721 8722 Input Parameters: 8723 + mat - the matrix 8724 . size - the initial size of the stash. 8725 - bsize - the initial size of the block-stash(if used). 8726 8727 Options Database Keys: 8728 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8729 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8730 8731 Level: intermediate 8732 8733 Notes: 8734 The block-stash is used for values set with `MatSetValuesBlocked()` while 8735 the stash is used for values set with `MatSetValues()` 8736 8737 Run with the option -info and look for output of the form 8738 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8739 to determine the appropriate value, MM, to use for size and 8740 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8741 to determine the value, BMM to use for bsize 8742 8743 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8744 @*/ 8745 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8746 { 8747 PetscFunctionBegin; 8748 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8749 PetscValidType(mat, 1); 8750 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8751 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8752 PetscFunctionReturn(PETSC_SUCCESS); 8753 } 8754 8755 /*@ 8756 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8757 the matrix 8758 8759 Neighbor-wise Collective 8760 8761 Input Parameters: 8762 + A - the matrix 8763 . x - the vector to be multiplied by the interpolation operator 8764 - y - the vector to be added to the result 8765 8766 Output Parameter: 8767 . w - the resulting vector 8768 8769 Level: intermediate 8770 8771 Notes: 8772 `w` may be the same vector as `y`. 8773 8774 This allows one to use either the restriction or interpolation (its transpose) 8775 matrix to do the interpolation 8776 8777 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8778 @*/ 8779 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8780 { 8781 PetscInt M, N, Ny; 8782 8783 PetscFunctionBegin; 8784 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8785 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8786 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8787 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8788 PetscCall(MatGetSize(A, &M, &N)); 8789 PetscCall(VecGetSize(y, &Ny)); 8790 if (M == Ny) { 8791 PetscCall(MatMultAdd(A, x, y, w)); 8792 } else { 8793 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8794 } 8795 PetscFunctionReturn(PETSC_SUCCESS); 8796 } 8797 8798 /*@ 8799 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8800 the matrix 8801 8802 Neighbor-wise Collective 8803 8804 Input Parameters: 8805 + A - the matrix 8806 - x - the vector to be interpolated 8807 8808 Output Parameter: 8809 . y - the resulting vector 8810 8811 Level: intermediate 8812 8813 Note: 8814 This allows one to use either the restriction or interpolation (its transpose) 8815 matrix to do the interpolation 8816 8817 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8818 @*/ 8819 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8820 { 8821 PetscInt M, N, Ny; 8822 8823 PetscFunctionBegin; 8824 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8825 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8826 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8827 PetscCall(MatGetSize(A, &M, &N)); 8828 PetscCall(VecGetSize(y, &Ny)); 8829 if (M == Ny) { 8830 PetscCall(MatMult(A, x, y)); 8831 } else { 8832 PetscCall(MatMultTranspose(A, x, y)); 8833 } 8834 PetscFunctionReturn(PETSC_SUCCESS); 8835 } 8836 8837 /*@ 8838 MatRestrict - $y = A*x$ or $A^T*x$ 8839 8840 Neighbor-wise Collective 8841 8842 Input Parameters: 8843 + A - the matrix 8844 - x - the vector to be restricted 8845 8846 Output Parameter: 8847 . y - the resulting vector 8848 8849 Level: intermediate 8850 8851 Note: 8852 This allows one to use either the restriction or interpolation (its transpose) 8853 matrix to do the restriction 8854 8855 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8856 @*/ 8857 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8858 { 8859 PetscInt M, N, Nx; 8860 8861 PetscFunctionBegin; 8862 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8863 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8864 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8865 PetscCall(MatGetSize(A, &M, &N)); 8866 PetscCall(VecGetSize(x, &Nx)); 8867 if (M == Nx) { 8868 PetscCall(MatMultTranspose(A, x, y)); 8869 } else { 8870 PetscCall(MatMult(A, x, y)); 8871 } 8872 PetscFunctionReturn(PETSC_SUCCESS); 8873 } 8874 8875 /*@ 8876 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8877 8878 Neighbor-wise Collective 8879 8880 Input Parameters: 8881 + A - the matrix 8882 . x - the input dense matrix to be multiplied 8883 - w - the input dense matrix to be added to the result 8884 8885 Output Parameter: 8886 . y - the output dense matrix 8887 8888 Level: intermediate 8889 8890 Note: 8891 This allows one to use either the restriction or interpolation (its transpose) 8892 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8893 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8894 8895 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8896 @*/ 8897 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8898 { 8899 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8900 PetscBool trans = PETSC_TRUE; 8901 MatReuse reuse = MAT_INITIAL_MATRIX; 8902 8903 PetscFunctionBegin; 8904 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8905 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8906 PetscValidType(x, 2); 8907 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8908 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8909 PetscCall(MatGetSize(A, &M, &N)); 8910 PetscCall(MatGetSize(x, &Mx, &Nx)); 8911 if (N == Mx) trans = PETSC_FALSE; 8912 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); 8913 Mo = trans ? N : M; 8914 if (*y) { 8915 PetscCall(MatGetSize(*y, &My, &Ny)); 8916 if (Mo == My && Nx == Ny) { 8917 reuse = MAT_REUSE_MATRIX; 8918 } else { 8919 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); 8920 PetscCall(MatDestroy(y)); 8921 } 8922 } 8923 8924 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8925 PetscBool flg; 8926 8927 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8928 if (w) { 8929 PetscInt My, Ny, Mw, Nw; 8930 8931 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8932 PetscCall(MatGetSize(*y, &My, &Ny)); 8933 PetscCall(MatGetSize(w, &Mw, &Nw)); 8934 if (!flg || My != Mw || Ny != Nw) w = NULL; 8935 } 8936 if (!w) { 8937 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8938 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8939 PetscCall(PetscObjectDereference((PetscObject)w)); 8940 } else { 8941 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8942 } 8943 } 8944 if (!trans) { 8945 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8946 } else { 8947 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8948 } 8949 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8950 PetscFunctionReturn(PETSC_SUCCESS); 8951 } 8952 8953 /*@ 8954 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8955 8956 Neighbor-wise Collective 8957 8958 Input Parameters: 8959 + A - the matrix 8960 - x - the input dense matrix 8961 8962 Output Parameter: 8963 . y - the output dense matrix 8964 8965 Level: intermediate 8966 8967 Note: 8968 This allows one to use either the restriction or interpolation (its transpose) 8969 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8970 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8971 8972 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8973 @*/ 8974 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8975 { 8976 PetscFunctionBegin; 8977 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8978 PetscFunctionReturn(PETSC_SUCCESS); 8979 } 8980 8981 /*@ 8982 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8983 8984 Neighbor-wise Collective 8985 8986 Input Parameters: 8987 + A - the matrix 8988 - x - the input dense matrix 8989 8990 Output Parameter: 8991 . y - the output dense matrix 8992 8993 Level: intermediate 8994 8995 Note: 8996 This allows one to use either the restriction or interpolation (its transpose) 8997 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8998 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8999 9000 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 9001 @*/ 9002 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 9003 { 9004 PetscFunctionBegin; 9005 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9006 PetscFunctionReturn(PETSC_SUCCESS); 9007 } 9008 9009 /*@ 9010 MatGetNullSpace - retrieves the null space of a matrix. 9011 9012 Logically Collective 9013 9014 Input Parameters: 9015 + mat - the matrix 9016 - nullsp - the null space object 9017 9018 Level: developer 9019 9020 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 9021 @*/ 9022 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 9023 { 9024 PetscFunctionBegin; 9025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9026 PetscAssertPointer(nullsp, 2); 9027 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 9028 PetscFunctionReturn(PETSC_SUCCESS); 9029 } 9030 9031 /*@C 9032 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9033 9034 Logically Collective 9035 9036 Input Parameters: 9037 + n - the number of matrices 9038 - mat - the array of matrices 9039 9040 Output Parameters: 9041 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9042 9043 Level: developer 9044 9045 Note: 9046 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9047 9048 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9049 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9050 @*/ 9051 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9052 { 9053 PetscFunctionBegin; 9054 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9055 PetscAssertPointer(mat, 2); 9056 PetscAssertPointer(nullsp, 3); 9057 9058 PetscCall(PetscCalloc1(3 * n, nullsp)); 9059 for (PetscInt i = 0; i < n; i++) { 9060 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9061 (*nullsp)[i] = mat[i]->nullsp; 9062 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9063 (*nullsp)[n + i] = mat[i]->nearnullsp; 9064 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9065 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9066 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9067 } 9068 PetscFunctionReturn(PETSC_SUCCESS); 9069 } 9070 9071 /*@C 9072 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9073 9074 Logically Collective 9075 9076 Input Parameters: 9077 + n - the number of matrices 9078 . mat - the array of matrices 9079 - nullsp - an array of null spaces 9080 9081 Level: developer 9082 9083 Note: 9084 Call `MatGetNullSpaces()` to create `nullsp` 9085 9086 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9087 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9088 @*/ 9089 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9090 { 9091 PetscFunctionBegin; 9092 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9093 PetscAssertPointer(mat, 2); 9094 PetscAssertPointer(nullsp, 3); 9095 PetscAssertPointer(*nullsp, 3); 9096 9097 for (PetscInt i = 0; i < n; i++) { 9098 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9099 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9100 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9101 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9102 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9103 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9104 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9105 } 9106 PetscCall(PetscFree(*nullsp)); 9107 PetscFunctionReturn(PETSC_SUCCESS); 9108 } 9109 9110 /*@ 9111 MatSetNullSpace - attaches a null space to a matrix. 9112 9113 Logically Collective 9114 9115 Input Parameters: 9116 + mat - the matrix 9117 - nullsp - the null space object 9118 9119 Level: advanced 9120 9121 Notes: 9122 This null space is used by the `KSP` linear solvers to solve singular systems. 9123 9124 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` 9125 9126 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 to 9127 to zero but the linear system will still be solved in a least squares sense. 9128 9129 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9130 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)$. 9131 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 9132 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 9133 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$). 9134 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9135 9136 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9137 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9138 routine also automatically calls `MatSetTransposeNullSpace()`. 9139 9140 The user should call `MatNullSpaceDestroy()`. 9141 9142 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9143 `KSPSetPCSide()` 9144 @*/ 9145 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9146 { 9147 PetscFunctionBegin; 9148 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9149 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9150 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9151 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9152 mat->nullsp = nullsp; 9153 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9154 PetscFunctionReturn(PETSC_SUCCESS); 9155 } 9156 9157 /*@ 9158 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9159 9160 Logically Collective 9161 9162 Input Parameters: 9163 + mat - the matrix 9164 - nullsp - the null space object 9165 9166 Level: developer 9167 9168 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9169 @*/ 9170 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9171 { 9172 PetscFunctionBegin; 9173 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9174 PetscValidType(mat, 1); 9175 PetscAssertPointer(nullsp, 2); 9176 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9177 PetscFunctionReturn(PETSC_SUCCESS); 9178 } 9179 9180 /*@ 9181 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9182 9183 Logically Collective 9184 9185 Input Parameters: 9186 + mat - the matrix 9187 - nullsp - the null space object 9188 9189 Level: advanced 9190 9191 Notes: 9192 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9193 9194 See `MatSetNullSpace()` 9195 9196 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9197 @*/ 9198 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9199 { 9200 PetscFunctionBegin; 9201 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9202 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9203 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9204 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9205 mat->transnullsp = nullsp; 9206 PetscFunctionReturn(PETSC_SUCCESS); 9207 } 9208 9209 /*@ 9210 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9211 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9212 9213 Logically Collective 9214 9215 Input Parameters: 9216 + mat - the matrix 9217 - nullsp - the null space object 9218 9219 Level: advanced 9220 9221 Notes: 9222 Overwrites any previous near null space that may have been attached 9223 9224 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9225 9226 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9227 @*/ 9228 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9229 { 9230 PetscFunctionBegin; 9231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9232 PetscValidType(mat, 1); 9233 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9234 MatCheckPreallocated(mat, 1); 9235 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9236 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9237 mat->nearnullsp = nullsp; 9238 PetscFunctionReturn(PETSC_SUCCESS); 9239 } 9240 9241 /*@ 9242 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9243 9244 Not Collective 9245 9246 Input Parameter: 9247 . mat - the matrix 9248 9249 Output Parameter: 9250 . nullsp - the null space object, `NULL` if not set 9251 9252 Level: advanced 9253 9254 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9255 @*/ 9256 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9257 { 9258 PetscFunctionBegin; 9259 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9260 PetscValidType(mat, 1); 9261 PetscAssertPointer(nullsp, 2); 9262 MatCheckPreallocated(mat, 1); 9263 *nullsp = mat->nearnullsp; 9264 PetscFunctionReturn(PETSC_SUCCESS); 9265 } 9266 9267 /*@ 9268 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9269 9270 Collective 9271 9272 Input Parameters: 9273 + mat - the matrix 9274 . row - row/column permutation 9275 - info - information on desired factorization process 9276 9277 Level: developer 9278 9279 Notes: 9280 Probably really in-place only when level of fill is zero, otherwise allocates 9281 new space to store factored matrix and deletes previous memory. 9282 9283 Most users should employ the `KSP` interface for linear solvers 9284 instead of working directly with matrix algebra routines such as this. 9285 See, e.g., `KSPCreate()`. 9286 9287 Developer Note: 9288 The Fortran interface is not autogenerated as the 9289 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9290 9291 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9292 @*/ 9293 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9294 { 9295 PetscFunctionBegin; 9296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9297 PetscValidType(mat, 1); 9298 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9299 PetscAssertPointer(info, 3); 9300 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9301 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9302 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9303 MatCheckPreallocated(mat, 1); 9304 PetscUseTypeMethod(mat, iccfactor, row, info); 9305 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9306 PetscFunctionReturn(PETSC_SUCCESS); 9307 } 9308 9309 /*@ 9310 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9311 ghosted ones. 9312 9313 Not Collective 9314 9315 Input Parameters: 9316 + mat - the matrix 9317 - diag - the diagonal values, including ghost ones 9318 9319 Level: developer 9320 9321 Notes: 9322 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9323 9324 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9325 9326 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9327 @*/ 9328 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9329 { 9330 PetscMPIInt size; 9331 9332 PetscFunctionBegin; 9333 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9334 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9335 PetscValidType(mat, 1); 9336 9337 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9338 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9339 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9340 if (size == 1) { 9341 PetscInt n, m; 9342 PetscCall(VecGetSize(diag, &n)); 9343 PetscCall(MatGetSize(mat, NULL, &m)); 9344 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9345 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9346 } else { 9347 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9348 } 9349 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9350 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9351 PetscFunctionReturn(PETSC_SUCCESS); 9352 } 9353 9354 /*@ 9355 MatGetInertia - Gets the inertia from a factored matrix 9356 9357 Collective 9358 9359 Input Parameter: 9360 . mat - the matrix 9361 9362 Output Parameters: 9363 + nneg - number of negative eigenvalues 9364 . nzero - number of zero eigenvalues 9365 - npos - number of positive eigenvalues 9366 9367 Level: advanced 9368 9369 Note: 9370 Matrix must have been factored by `MatCholeskyFactor()` 9371 9372 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9373 @*/ 9374 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9375 { 9376 PetscFunctionBegin; 9377 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9378 PetscValidType(mat, 1); 9379 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9380 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9381 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9382 PetscFunctionReturn(PETSC_SUCCESS); 9383 } 9384 9385 /*@C 9386 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9387 9388 Neighbor-wise Collective 9389 9390 Input Parameters: 9391 + mat - the factored matrix obtained with `MatGetFactor()` 9392 - b - the right-hand-side vectors 9393 9394 Output Parameter: 9395 . x - the result vectors 9396 9397 Level: developer 9398 9399 Note: 9400 The vectors `b` and `x` cannot be the same. I.e., one cannot 9401 call `MatSolves`(A,x,x). 9402 9403 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9404 @*/ 9405 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9406 { 9407 PetscFunctionBegin; 9408 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9409 PetscValidType(mat, 1); 9410 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9411 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9412 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9413 9414 MatCheckPreallocated(mat, 1); 9415 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9416 PetscUseTypeMethod(mat, solves, b, x); 9417 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9418 PetscFunctionReturn(PETSC_SUCCESS); 9419 } 9420 9421 /*@ 9422 MatIsSymmetric - Test whether a matrix is symmetric 9423 9424 Collective 9425 9426 Input Parameters: 9427 + A - the matrix to test 9428 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9429 9430 Output Parameter: 9431 . flg - the result 9432 9433 Level: intermediate 9434 9435 Notes: 9436 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9437 9438 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9439 9440 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9441 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9442 9443 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9444 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9445 @*/ 9446 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9447 { 9448 PetscFunctionBegin; 9449 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9450 PetscAssertPointer(flg, 3); 9451 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9452 else { 9453 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9454 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9455 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9456 } 9457 PetscFunctionReturn(PETSC_SUCCESS); 9458 } 9459 9460 /*@ 9461 MatIsHermitian - Test whether a matrix is Hermitian 9462 9463 Collective 9464 9465 Input Parameters: 9466 + A - the matrix to test 9467 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9468 9469 Output Parameter: 9470 . flg - the result 9471 9472 Level: intermediate 9473 9474 Notes: 9475 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9476 9477 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9478 9479 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9480 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9481 9482 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9483 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9484 @*/ 9485 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9486 { 9487 PetscFunctionBegin; 9488 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9489 PetscAssertPointer(flg, 3); 9490 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9491 else { 9492 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9493 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9494 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9495 } 9496 PetscFunctionReturn(PETSC_SUCCESS); 9497 } 9498 9499 /*@ 9500 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9501 9502 Not Collective 9503 9504 Input Parameter: 9505 . A - the matrix to check 9506 9507 Output Parameters: 9508 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9509 - flg - the result (only valid if set is `PETSC_TRUE`) 9510 9511 Level: advanced 9512 9513 Notes: 9514 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9515 if you want it explicitly checked 9516 9517 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9518 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9519 9520 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9521 @*/ 9522 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9523 { 9524 PetscFunctionBegin; 9525 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9526 PetscAssertPointer(set, 2); 9527 PetscAssertPointer(flg, 3); 9528 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9529 *set = PETSC_TRUE; 9530 *flg = PetscBool3ToBool(A->symmetric); 9531 } else { 9532 *set = PETSC_FALSE; 9533 } 9534 PetscFunctionReturn(PETSC_SUCCESS); 9535 } 9536 9537 /*@ 9538 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9539 9540 Not Collective 9541 9542 Input Parameter: 9543 . A - the matrix to check 9544 9545 Output Parameters: 9546 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9547 - flg - the result (only valid if set is `PETSC_TRUE`) 9548 9549 Level: advanced 9550 9551 Notes: 9552 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9553 9554 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9555 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9556 9557 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9558 @*/ 9559 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9560 { 9561 PetscFunctionBegin; 9562 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9563 PetscAssertPointer(set, 2); 9564 PetscAssertPointer(flg, 3); 9565 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9566 *set = PETSC_TRUE; 9567 *flg = PetscBool3ToBool(A->spd); 9568 } else { 9569 *set = PETSC_FALSE; 9570 } 9571 PetscFunctionReturn(PETSC_SUCCESS); 9572 } 9573 9574 /*@ 9575 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9576 9577 Not Collective 9578 9579 Input Parameter: 9580 . A - the matrix to check 9581 9582 Output Parameters: 9583 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9584 - flg - the result (only valid if set is `PETSC_TRUE`) 9585 9586 Level: advanced 9587 9588 Notes: 9589 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9590 if you want it explicitly checked 9591 9592 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9593 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9594 9595 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9596 @*/ 9597 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9598 { 9599 PetscFunctionBegin; 9600 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9601 PetscAssertPointer(set, 2); 9602 PetscAssertPointer(flg, 3); 9603 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9604 *set = PETSC_TRUE; 9605 *flg = PetscBool3ToBool(A->hermitian); 9606 } else { 9607 *set = PETSC_FALSE; 9608 } 9609 PetscFunctionReturn(PETSC_SUCCESS); 9610 } 9611 9612 /*@ 9613 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9614 9615 Collective 9616 9617 Input Parameter: 9618 . A - the matrix to test 9619 9620 Output Parameter: 9621 . flg - the result 9622 9623 Level: intermediate 9624 9625 Notes: 9626 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9627 9628 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 9629 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9630 9631 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9632 @*/ 9633 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9634 { 9635 PetscFunctionBegin; 9636 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9637 PetscAssertPointer(flg, 2); 9638 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9639 *flg = PetscBool3ToBool(A->structurally_symmetric); 9640 } else { 9641 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9642 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9643 } 9644 PetscFunctionReturn(PETSC_SUCCESS); 9645 } 9646 9647 /*@ 9648 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9649 9650 Not Collective 9651 9652 Input Parameter: 9653 . A - the matrix to check 9654 9655 Output Parameters: 9656 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9657 - flg - the result (only valid if set is PETSC_TRUE) 9658 9659 Level: advanced 9660 9661 Notes: 9662 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 9663 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9664 9665 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9666 9667 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9668 @*/ 9669 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9670 { 9671 PetscFunctionBegin; 9672 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9673 PetscAssertPointer(set, 2); 9674 PetscAssertPointer(flg, 3); 9675 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9676 *set = PETSC_TRUE; 9677 *flg = PetscBool3ToBool(A->structurally_symmetric); 9678 } else { 9679 *set = PETSC_FALSE; 9680 } 9681 PetscFunctionReturn(PETSC_SUCCESS); 9682 } 9683 9684 /*@ 9685 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9686 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9687 9688 Not Collective 9689 9690 Input Parameter: 9691 . mat - the matrix 9692 9693 Output Parameters: 9694 + nstash - the size of the stash 9695 . reallocs - the number of additional mallocs incurred. 9696 . bnstash - the size of the block stash 9697 - breallocs - the number of additional mallocs incurred.in the block stash 9698 9699 Level: advanced 9700 9701 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9702 @*/ 9703 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9704 { 9705 PetscFunctionBegin; 9706 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9707 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9708 PetscFunctionReturn(PETSC_SUCCESS); 9709 } 9710 9711 /*@ 9712 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9713 parallel layout, `PetscLayout` for rows and columns 9714 9715 Collective 9716 9717 Input Parameter: 9718 . mat - the matrix 9719 9720 Output Parameters: 9721 + right - (optional) vector that the matrix can be multiplied against 9722 - left - (optional) vector that the matrix vector product can be stored in 9723 9724 Level: advanced 9725 9726 Notes: 9727 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()`. 9728 9729 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9730 9731 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9732 @*/ 9733 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9734 { 9735 PetscFunctionBegin; 9736 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9737 PetscValidType(mat, 1); 9738 if (mat->ops->getvecs) { 9739 PetscUseTypeMethod(mat, getvecs, right, left); 9740 } else { 9741 if (right) { 9742 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9743 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9744 PetscCall(VecSetType(*right, mat->defaultvectype)); 9745 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9746 if (mat->boundtocpu && mat->bindingpropagates) { 9747 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9748 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9749 } 9750 #endif 9751 } 9752 if (left) { 9753 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9754 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9755 PetscCall(VecSetType(*left, mat->defaultvectype)); 9756 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9757 if (mat->boundtocpu && mat->bindingpropagates) { 9758 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9759 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9760 } 9761 #endif 9762 } 9763 } 9764 PetscFunctionReturn(PETSC_SUCCESS); 9765 } 9766 9767 /*@ 9768 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9769 with default values. 9770 9771 Not Collective 9772 9773 Input Parameter: 9774 . info - the `MatFactorInfo` data structure 9775 9776 Level: developer 9777 9778 Notes: 9779 The solvers are generally used through the `KSP` and `PC` objects, for example 9780 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9781 9782 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9783 9784 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9785 @*/ 9786 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9787 { 9788 PetscFunctionBegin; 9789 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9790 PetscFunctionReturn(PETSC_SUCCESS); 9791 } 9792 9793 /*@ 9794 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9795 9796 Collective 9797 9798 Input Parameters: 9799 + mat - the factored matrix 9800 - is - the index set defining the Schur indices (0-based) 9801 9802 Level: advanced 9803 9804 Notes: 9805 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9806 9807 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9808 9809 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9810 9811 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9812 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9813 @*/ 9814 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9815 { 9816 PetscErrorCode (*f)(Mat, IS); 9817 9818 PetscFunctionBegin; 9819 PetscValidType(mat, 1); 9820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9821 PetscValidType(is, 2); 9822 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9823 PetscCheckSameComm(mat, 1, is, 2); 9824 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9825 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9826 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9827 PetscCall(MatDestroy(&mat->schur)); 9828 PetscCall((*f)(mat, is)); 9829 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9830 PetscFunctionReturn(PETSC_SUCCESS); 9831 } 9832 9833 /*@ 9834 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9835 9836 Logically Collective 9837 9838 Input Parameters: 9839 + F - the factored matrix obtained by calling `MatGetFactor()` 9840 . S - location where to return the Schur complement, can be `NULL` 9841 - status - the status of the Schur complement matrix, can be `NULL` 9842 9843 Level: advanced 9844 9845 Notes: 9846 You must call `MatFactorSetSchurIS()` before calling this routine. 9847 9848 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9849 9850 The routine provides a copy of the Schur matrix stored within the solver data structures. 9851 The caller must destroy the object when it is no longer needed. 9852 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9853 9854 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) 9855 9856 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9857 9858 Developer Note: 9859 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9860 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9861 9862 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9863 @*/ 9864 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9865 { 9866 PetscFunctionBegin; 9867 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9868 if (S) PetscAssertPointer(S, 2); 9869 if (status) PetscAssertPointer(status, 3); 9870 if (S) { 9871 PetscErrorCode (*f)(Mat, Mat *); 9872 9873 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9874 if (f) { 9875 PetscCall((*f)(F, S)); 9876 } else { 9877 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9878 } 9879 } 9880 if (status) *status = F->schur_status; 9881 PetscFunctionReturn(PETSC_SUCCESS); 9882 } 9883 9884 /*@ 9885 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9886 9887 Logically Collective 9888 9889 Input Parameters: 9890 + F - the factored matrix obtained by calling `MatGetFactor()` 9891 . S - location where to return the Schur complement, can be `NULL` 9892 - status - the status of the Schur complement matrix, can be `NULL` 9893 9894 Level: advanced 9895 9896 Notes: 9897 You must call `MatFactorSetSchurIS()` before calling this routine. 9898 9899 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9900 9901 The routine returns a the Schur Complement stored within the data structures of the solver. 9902 9903 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9904 9905 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9906 9907 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9908 9909 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9910 9911 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9912 @*/ 9913 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9914 { 9915 PetscFunctionBegin; 9916 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9917 if (S) { 9918 PetscAssertPointer(S, 2); 9919 *S = F->schur; 9920 } 9921 if (status) { 9922 PetscAssertPointer(status, 3); 9923 *status = F->schur_status; 9924 } 9925 PetscFunctionReturn(PETSC_SUCCESS); 9926 } 9927 9928 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9929 { 9930 Mat S = F->schur; 9931 9932 PetscFunctionBegin; 9933 switch (F->schur_status) { 9934 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9935 case MAT_FACTOR_SCHUR_INVERTED: 9936 if (S) { 9937 S->ops->solve = NULL; 9938 S->ops->matsolve = NULL; 9939 S->ops->solvetranspose = NULL; 9940 S->ops->matsolvetranspose = NULL; 9941 S->ops->solveadd = NULL; 9942 S->ops->solvetransposeadd = NULL; 9943 S->factortype = MAT_FACTOR_NONE; 9944 PetscCall(PetscFree(S->solvertype)); 9945 } 9946 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9947 break; 9948 default: 9949 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9950 } 9951 PetscFunctionReturn(PETSC_SUCCESS); 9952 } 9953 9954 /*@ 9955 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9956 9957 Logically Collective 9958 9959 Input Parameters: 9960 + F - the factored matrix obtained by calling `MatGetFactor()` 9961 . S - location where the Schur complement is stored 9962 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9963 9964 Level: advanced 9965 9966 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9967 @*/ 9968 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9969 { 9970 PetscFunctionBegin; 9971 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9972 if (S) { 9973 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9974 *S = NULL; 9975 } 9976 F->schur_status = status; 9977 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9978 PetscFunctionReturn(PETSC_SUCCESS); 9979 } 9980 9981 /*@ 9982 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9983 9984 Logically Collective 9985 9986 Input Parameters: 9987 + F - the factored matrix obtained by calling `MatGetFactor()` 9988 . rhs - location where the right-hand side of the Schur complement system is stored 9989 - sol - location where the solution of the Schur complement system has to be returned 9990 9991 Level: advanced 9992 9993 Notes: 9994 The sizes of the vectors should match the size of the Schur complement 9995 9996 Must be called after `MatFactorSetSchurIS()` 9997 9998 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9999 @*/ 10000 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 10001 { 10002 PetscFunctionBegin; 10003 PetscValidType(F, 1); 10004 PetscValidType(rhs, 2); 10005 PetscValidType(sol, 3); 10006 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10007 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10008 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10009 PetscCheckSameComm(F, 1, rhs, 2); 10010 PetscCheckSameComm(F, 1, sol, 3); 10011 PetscCall(MatFactorFactorizeSchurComplement(F)); 10012 switch (F->schur_status) { 10013 case MAT_FACTOR_SCHUR_FACTORED: 10014 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 10015 break; 10016 case MAT_FACTOR_SCHUR_INVERTED: 10017 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 10018 break; 10019 default: 10020 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10021 } 10022 PetscFunctionReturn(PETSC_SUCCESS); 10023 } 10024 10025 /*@ 10026 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 10027 10028 Logically Collective 10029 10030 Input Parameters: 10031 + F - the factored matrix obtained by calling `MatGetFactor()` 10032 . rhs - location where the right-hand side of the Schur complement system is stored 10033 - sol - location where the solution of the Schur complement system has to be returned 10034 10035 Level: advanced 10036 10037 Notes: 10038 The sizes of the vectors should match the size of the Schur complement 10039 10040 Must be called after `MatFactorSetSchurIS()` 10041 10042 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10043 @*/ 10044 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10045 { 10046 PetscFunctionBegin; 10047 PetscValidType(F, 1); 10048 PetscValidType(rhs, 2); 10049 PetscValidType(sol, 3); 10050 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10051 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10052 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10053 PetscCheckSameComm(F, 1, rhs, 2); 10054 PetscCheckSameComm(F, 1, sol, 3); 10055 PetscCall(MatFactorFactorizeSchurComplement(F)); 10056 switch (F->schur_status) { 10057 case MAT_FACTOR_SCHUR_FACTORED: 10058 PetscCall(MatSolve(F->schur, rhs, sol)); 10059 break; 10060 case MAT_FACTOR_SCHUR_INVERTED: 10061 PetscCall(MatMult(F->schur, rhs, sol)); 10062 break; 10063 default: 10064 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10065 } 10066 PetscFunctionReturn(PETSC_SUCCESS); 10067 } 10068 10069 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10070 #if PetscDefined(HAVE_CUDA) 10071 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10072 #endif 10073 10074 /* Schur status updated in the interface */ 10075 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10076 { 10077 Mat S = F->schur; 10078 10079 PetscFunctionBegin; 10080 if (S) { 10081 PetscMPIInt size; 10082 PetscBool isdense, isdensecuda; 10083 10084 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10085 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10086 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10087 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10088 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10089 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10090 if (isdense) { 10091 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10092 } else if (isdensecuda) { 10093 #if defined(PETSC_HAVE_CUDA) 10094 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10095 #endif 10096 } 10097 // HIP?????????????? 10098 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10099 } 10100 PetscFunctionReturn(PETSC_SUCCESS); 10101 } 10102 10103 /*@ 10104 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10105 10106 Logically Collective 10107 10108 Input Parameter: 10109 . F - the factored matrix obtained by calling `MatGetFactor()` 10110 10111 Level: advanced 10112 10113 Notes: 10114 Must be called after `MatFactorSetSchurIS()`. 10115 10116 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10117 10118 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10119 @*/ 10120 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10121 { 10122 PetscFunctionBegin; 10123 PetscValidType(F, 1); 10124 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10125 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10126 PetscCall(MatFactorFactorizeSchurComplement(F)); 10127 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10128 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10129 PetscFunctionReturn(PETSC_SUCCESS); 10130 } 10131 10132 /*@ 10133 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10134 10135 Logically Collective 10136 10137 Input Parameter: 10138 . F - the factored matrix obtained by calling `MatGetFactor()` 10139 10140 Level: advanced 10141 10142 Note: 10143 Must be called after `MatFactorSetSchurIS()` 10144 10145 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10146 @*/ 10147 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10148 { 10149 MatFactorInfo info; 10150 10151 PetscFunctionBegin; 10152 PetscValidType(F, 1); 10153 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10154 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10155 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10156 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10157 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10158 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10159 } else { 10160 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10161 } 10162 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10163 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10164 PetscFunctionReturn(PETSC_SUCCESS); 10165 } 10166 10167 /*@ 10168 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10169 10170 Neighbor-wise Collective 10171 10172 Input Parameters: 10173 + A - the matrix 10174 . P - the projection matrix 10175 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10176 - 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 10177 if the result is a dense matrix this is irrelevant 10178 10179 Output Parameter: 10180 . C - the product matrix 10181 10182 Level: intermediate 10183 10184 Notes: 10185 C will be created and must be destroyed by the user with `MatDestroy()`. 10186 10187 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10188 10189 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10190 10191 Developer Note: 10192 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10193 10194 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10195 @*/ 10196 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10197 { 10198 PetscFunctionBegin; 10199 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10200 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10201 10202 if (scall == MAT_INITIAL_MATRIX) { 10203 PetscCall(MatProductCreate(A, P, NULL, C)); 10204 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10205 PetscCall(MatProductSetAlgorithm(*C, "default")); 10206 PetscCall(MatProductSetFill(*C, fill)); 10207 10208 (*C)->product->api_user = PETSC_TRUE; 10209 PetscCall(MatProductSetFromOptions(*C)); 10210 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); 10211 PetscCall(MatProductSymbolic(*C)); 10212 } else { /* scall == MAT_REUSE_MATRIX */ 10213 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10214 } 10215 10216 PetscCall(MatProductNumeric(*C)); 10217 (*C)->symmetric = A->symmetric; 10218 (*C)->spd = A->spd; 10219 PetscFunctionReturn(PETSC_SUCCESS); 10220 } 10221 10222 /*@ 10223 MatRARt - Creates the matrix product $C = R * A * R^T$ 10224 10225 Neighbor-wise Collective 10226 10227 Input Parameters: 10228 + A - the matrix 10229 . R - the projection matrix 10230 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10231 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10232 if the result is a dense matrix this is irrelevant 10233 10234 Output Parameter: 10235 . C - the product matrix 10236 10237 Level: intermediate 10238 10239 Notes: 10240 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10241 10242 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10243 10244 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10245 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10246 parallel `MatRARt()` is implemented via explicit transpose of `R`, which could be very expensive. 10247 We recommend using `MatPtAP()`. 10248 10249 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10250 10251 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10252 @*/ 10253 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10254 { 10255 PetscFunctionBegin; 10256 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10257 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10258 10259 if (scall == MAT_INITIAL_MATRIX) { 10260 PetscCall(MatProductCreate(A, R, NULL, C)); 10261 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10262 PetscCall(MatProductSetAlgorithm(*C, "default")); 10263 PetscCall(MatProductSetFill(*C, fill)); 10264 10265 (*C)->product->api_user = PETSC_TRUE; 10266 PetscCall(MatProductSetFromOptions(*C)); 10267 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); 10268 PetscCall(MatProductSymbolic(*C)); 10269 } else { /* scall == MAT_REUSE_MATRIX */ 10270 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10271 } 10272 10273 PetscCall(MatProductNumeric(*C)); 10274 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10275 PetscFunctionReturn(PETSC_SUCCESS); 10276 } 10277 10278 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10279 { 10280 PetscBool flg = PETSC_TRUE; 10281 10282 PetscFunctionBegin; 10283 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10284 if (scall == MAT_INITIAL_MATRIX) { 10285 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10286 PetscCall(MatProductCreate(A, B, NULL, C)); 10287 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10288 PetscCall(MatProductSetFill(*C, fill)); 10289 } else { /* scall == MAT_REUSE_MATRIX */ 10290 Mat_Product *product = (*C)->product; 10291 10292 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10293 if (flg && product && product->type != ptype) { 10294 PetscCall(MatProductClear(*C)); 10295 product = NULL; 10296 } 10297 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10298 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10299 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10300 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10301 product = (*C)->product; 10302 product->fill = fill; 10303 product->clear = PETSC_TRUE; 10304 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10305 flg = PETSC_FALSE; 10306 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10307 } 10308 } 10309 if (flg) { 10310 (*C)->product->api_user = PETSC_TRUE; 10311 PetscCall(MatProductSetType(*C, ptype)); 10312 PetscCall(MatProductSetFromOptions(*C)); 10313 PetscCall(MatProductSymbolic(*C)); 10314 } 10315 PetscCall(MatProductNumeric(*C)); 10316 PetscFunctionReturn(PETSC_SUCCESS); 10317 } 10318 10319 /*@ 10320 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10321 10322 Neighbor-wise Collective 10323 10324 Input Parameters: 10325 + A - the left matrix 10326 . B - the right matrix 10327 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10328 - 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 10329 if the result is a dense matrix this is irrelevant 10330 10331 Output Parameter: 10332 . C - the product matrix 10333 10334 Notes: 10335 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10336 10337 `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 10338 call to this function with `MAT_INITIAL_MATRIX`. 10339 10340 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10341 10342 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`, 10343 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10344 10345 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10346 10347 Example of Usage: 10348 .vb 10349 MatProductCreate(A,B,NULL,&C); 10350 MatProductSetType(C,MATPRODUCT_AB); 10351 MatProductSymbolic(C); 10352 MatProductNumeric(C); // compute C=A * B 10353 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10354 MatProductNumeric(C); 10355 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10356 MatProductNumeric(C); 10357 .ve 10358 10359 Level: intermediate 10360 10361 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10362 @*/ 10363 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10364 { 10365 PetscFunctionBegin; 10366 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10367 PetscFunctionReturn(PETSC_SUCCESS); 10368 } 10369 10370 /*@ 10371 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10372 10373 Neighbor-wise Collective 10374 10375 Input Parameters: 10376 + A - the left matrix 10377 . B - the right matrix 10378 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10379 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10380 10381 Output Parameter: 10382 . C - the product matrix 10383 10384 Options Database Key: 10385 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10386 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10387 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10388 10389 Level: intermediate 10390 10391 Notes: 10392 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10393 10394 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10395 10396 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10397 actually needed. 10398 10399 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10400 and for pairs of `MATMPIDENSE` matrices. 10401 10402 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10403 10404 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10405 10406 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10407 @*/ 10408 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10409 { 10410 PetscFunctionBegin; 10411 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10412 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10413 PetscFunctionReturn(PETSC_SUCCESS); 10414 } 10415 10416 /*@ 10417 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10418 10419 Neighbor-wise Collective 10420 10421 Input Parameters: 10422 + A - the left matrix 10423 . B - the right matrix 10424 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10425 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10426 10427 Output Parameter: 10428 . C - the product matrix 10429 10430 Level: intermediate 10431 10432 Notes: 10433 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10434 10435 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10436 10437 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10438 10439 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10440 actually needed. 10441 10442 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10443 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10444 10445 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10446 10447 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10448 @*/ 10449 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10450 { 10451 PetscFunctionBegin; 10452 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10453 PetscFunctionReturn(PETSC_SUCCESS); 10454 } 10455 10456 /*@ 10457 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10458 10459 Neighbor-wise Collective 10460 10461 Input Parameters: 10462 + A - the left matrix 10463 . B - the middle matrix 10464 . C - the right matrix 10465 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10466 - 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 10467 if the result is a dense matrix this is irrelevant 10468 10469 Output Parameter: 10470 . D - the product matrix 10471 10472 Level: intermediate 10473 10474 Notes: 10475 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10476 10477 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10478 10479 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10480 10481 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10482 actually needed. 10483 10484 If you have many matrices with the same non-zero structure to multiply, you 10485 should use `MAT_REUSE_MATRIX` in all calls but the first 10486 10487 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10488 10489 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10490 @*/ 10491 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10492 { 10493 PetscFunctionBegin; 10494 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10495 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10496 10497 if (scall == MAT_INITIAL_MATRIX) { 10498 PetscCall(MatProductCreate(A, B, C, D)); 10499 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10500 PetscCall(MatProductSetAlgorithm(*D, "default")); 10501 PetscCall(MatProductSetFill(*D, fill)); 10502 10503 (*D)->product->api_user = PETSC_TRUE; 10504 PetscCall(MatProductSetFromOptions(*D)); 10505 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, 10506 ((PetscObject)C)->type_name); 10507 PetscCall(MatProductSymbolic(*D)); 10508 } else { /* user may change input matrices when REUSE */ 10509 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10510 } 10511 PetscCall(MatProductNumeric(*D)); 10512 PetscFunctionReturn(PETSC_SUCCESS); 10513 } 10514 10515 /*@ 10516 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10517 10518 Collective 10519 10520 Input Parameters: 10521 + mat - the matrix 10522 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10523 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10524 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10525 10526 Output Parameter: 10527 . matredundant - redundant matrix 10528 10529 Level: advanced 10530 10531 Notes: 10532 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10533 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10534 10535 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10536 calling it. 10537 10538 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10539 10540 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10541 @*/ 10542 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10543 { 10544 MPI_Comm comm; 10545 PetscMPIInt size; 10546 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10547 Mat_Redundant *redund = NULL; 10548 PetscSubcomm psubcomm = NULL; 10549 MPI_Comm subcomm_in = subcomm; 10550 Mat *matseq; 10551 IS isrow, iscol; 10552 PetscBool newsubcomm = PETSC_FALSE; 10553 10554 PetscFunctionBegin; 10555 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10556 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10557 PetscAssertPointer(*matredundant, 5); 10558 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10559 } 10560 10561 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10562 if (size == 1 || nsubcomm == 1) { 10563 if (reuse == MAT_INITIAL_MATRIX) { 10564 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10565 } else { 10566 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"); 10567 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10568 } 10569 PetscFunctionReturn(PETSC_SUCCESS); 10570 } 10571 10572 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10573 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10574 MatCheckPreallocated(mat, 1); 10575 10576 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10577 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10578 /* create psubcomm, then get subcomm */ 10579 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10580 PetscCallMPI(MPI_Comm_size(comm, &size)); 10581 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10582 10583 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10584 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10585 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10586 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10587 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10588 newsubcomm = PETSC_TRUE; 10589 PetscCall(PetscSubcommDestroy(&psubcomm)); 10590 } 10591 10592 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10593 if (reuse == MAT_INITIAL_MATRIX) { 10594 mloc_sub = PETSC_DECIDE; 10595 nloc_sub = PETSC_DECIDE; 10596 if (bs < 1) { 10597 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10598 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10599 } else { 10600 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10601 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10602 } 10603 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10604 rstart = rend - mloc_sub; 10605 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10606 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10607 PetscCall(ISSetIdentity(iscol)); 10608 } else { /* reuse == MAT_REUSE_MATRIX */ 10609 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"); 10610 /* retrieve subcomm */ 10611 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10612 redund = (*matredundant)->redundant; 10613 isrow = redund->isrow; 10614 iscol = redund->iscol; 10615 matseq = redund->matseq; 10616 } 10617 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10618 10619 /* get matredundant over subcomm */ 10620 if (reuse == MAT_INITIAL_MATRIX) { 10621 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10622 10623 /* create a supporting struct and attach it to C for reuse */ 10624 PetscCall(PetscNew(&redund)); 10625 (*matredundant)->redundant = redund; 10626 redund->isrow = isrow; 10627 redund->iscol = iscol; 10628 redund->matseq = matseq; 10629 if (newsubcomm) { 10630 redund->subcomm = subcomm; 10631 } else { 10632 redund->subcomm = MPI_COMM_NULL; 10633 } 10634 } else { 10635 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10636 } 10637 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10638 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10639 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10640 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10641 } 10642 #endif 10643 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10644 PetscFunctionReturn(PETSC_SUCCESS); 10645 } 10646 10647 /*@C 10648 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10649 a given `Mat`. Each submatrix can span multiple procs. 10650 10651 Collective 10652 10653 Input Parameters: 10654 + mat - the matrix 10655 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10656 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10657 10658 Output Parameter: 10659 . subMat - parallel sub-matrices each spanning a given `subcomm` 10660 10661 Level: advanced 10662 10663 Notes: 10664 The submatrix partition across processors is dictated by `subComm` a 10665 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10666 is not restricted to be grouped with consecutive original MPI processes. 10667 10668 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10669 map directly to the layout of the original matrix [wrt the local 10670 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10671 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10672 the `subMat`. However the offDiagMat looses some columns - and this is 10673 reconstructed with `MatSetValues()` 10674 10675 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10676 10677 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10678 @*/ 10679 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10680 { 10681 PetscMPIInt commsize, subCommSize; 10682 10683 PetscFunctionBegin; 10684 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10685 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10686 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10687 10688 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"); 10689 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10690 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10691 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10692 PetscFunctionReturn(PETSC_SUCCESS); 10693 } 10694 10695 /*@ 10696 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10697 10698 Not Collective 10699 10700 Input Parameters: 10701 + mat - matrix to extract local submatrix from 10702 . isrow - local row indices for submatrix 10703 - iscol - local column indices for submatrix 10704 10705 Output Parameter: 10706 . submat - the submatrix 10707 10708 Level: intermediate 10709 10710 Notes: 10711 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10712 10713 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10714 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10715 10716 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10717 `MatSetValuesBlockedLocal()` will also be implemented. 10718 10719 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10720 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10721 10722 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10723 @*/ 10724 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10725 { 10726 PetscFunctionBegin; 10727 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10728 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10729 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10730 PetscCheckSameComm(isrow, 2, iscol, 3); 10731 PetscAssertPointer(submat, 4); 10732 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10733 10734 if (mat->ops->getlocalsubmatrix) { 10735 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10736 } else { 10737 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10738 } 10739 PetscFunctionReturn(PETSC_SUCCESS); 10740 } 10741 10742 /*@ 10743 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10744 10745 Not Collective 10746 10747 Input Parameters: 10748 + mat - matrix to extract local submatrix from 10749 . isrow - local row indices for submatrix 10750 . iscol - local column indices for submatrix 10751 - submat - the submatrix 10752 10753 Level: intermediate 10754 10755 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10756 @*/ 10757 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10758 { 10759 PetscFunctionBegin; 10760 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10761 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10762 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10763 PetscCheckSameComm(isrow, 2, iscol, 3); 10764 PetscAssertPointer(submat, 4); 10765 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10766 10767 if (mat->ops->restorelocalsubmatrix) { 10768 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10769 } else { 10770 PetscCall(MatDestroy(submat)); 10771 } 10772 *submat = NULL; 10773 PetscFunctionReturn(PETSC_SUCCESS); 10774 } 10775 10776 /*@ 10777 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10778 10779 Collective 10780 10781 Input Parameter: 10782 . mat - the matrix 10783 10784 Output Parameter: 10785 . is - if any rows have zero diagonals this contains the list of them 10786 10787 Level: developer 10788 10789 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10790 @*/ 10791 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10792 { 10793 PetscFunctionBegin; 10794 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10795 PetscValidType(mat, 1); 10796 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10797 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10798 10799 if (!mat->ops->findzerodiagonals) { 10800 Vec diag; 10801 const PetscScalar *a; 10802 PetscInt *rows; 10803 PetscInt rStart, rEnd, r, nrow = 0; 10804 10805 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10806 PetscCall(MatGetDiagonal(mat, diag)); 10807 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10808 PetscCall(VecGetArrayRead(diag, &a)); 10809 for (r = 0; r < rEnd - rStart; ++r) 10810 if (a[r] == 0.0) ++nrow; 10811 PetscCall(PetscMalloc1(nrow, &rows)); 10812 nrow = 0; 10813 for (r = 0; r < rEnd - rStart; ++r) 10814 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10815 PetscCall(VecRestoreArrayRead(diag, &a)); 10816 PetscCall(VecDestroy(&diag)); 10817 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10818 } else { 10819 PetscUseTypeMethod(mat, findzerodiagonals, is); 10820 } 10821 PetscFunctionReturn(PETSC_SUCCESS); 10822 } 10823 10824 /*@ 10825 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10826 10827 Collective 10828 10829 Input Parameter: 10830 . mat - the matrix 10831 10832 Output Parameter: 10833 . is - contains the list of rows with off block diagonal entries 10834 10835 Level: developer 10836 10837 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10838 @*/ 10839 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10840 { 10841 PetscFunctionBegin; 10842 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10843 PetscValidType(mat, 1); 10844 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10846 10847 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10848 PetscFunctionReturn(PETSC_SUCCESS); 10849 } 10850 10851 /*@C 10852 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10853 10854 Collective; No Fortran Support 10855 10856 Input Parameter: 10857 . mat - the matrix 10858 10859 Output Parameter: 10860 . values - the block inverses in column major order (FORTRAN-like) 10861 10862 Level: advanced 10863 10864 Notes: 10865 The size of the blocks is determined by the block size of the matrix. 10866 10867 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10868 10869 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10870 10871 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10872 @*/ 10873 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10874 { 10875 PetscFunctionBegin; 10876 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10877 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10878 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10879 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10880 PetscFunctionReturn(PETSC_SUCCESS); 10881 } 10882 10883 /*@ 10884 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10885 10886 Collective; No Fortran Support 10887 10888 Input Parameters: 10889 + mat - the matrix 10890 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10891 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10892 10893 Output Parameter: 10894 . values - the block inverses in column major order (FORTRAN-like) 10895 10896 Level: advanced 10897 10898 Notes: 10899 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10900 10901 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10902 10903 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10904 @*/ 10905 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10906 { 10907 PetscFunctionBegin; 10908 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10909 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10910 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10911 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10912 PetscFunctionReturn(PETSC_SUCCESS); 10913 } 10914 10915 /*@ 10916 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10917 10918 Collective 10919 10920 Input Parameters: 10921 + A - the matrix 10922 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10923 10924 Level: advanced 10925 10926 Note: 10927 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10928 10929 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10930 @*/ 10931 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10932 { 10933 const PetscScalar *vals; 10934 PetscInt *dnnz; 10935 PetscInt m, rstart, rend, bs, i, j; 10936 10937 PetscFunctionBegin; 10938 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10939 PetscCall(MatGetBlockSize(A, &bs)); 10940 PetscCall(MatGetLocalSize(A, &m, NULL)); 10941 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10942 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10943 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10944 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10945 PetscCall(PetscFree(dnnz)); 10946 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10947 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10948 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10949 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10950 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10951 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10952 PetscFunctionReturn(PETSC_SUCCESS); 10953 } 10954 10955 /*@ 10956 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10957 via `MatTransposeColoringCreate()`. 10958 10959 Collective 10960 10961 Input Parameter: 10962 . c - coloring context 10963 10964 Level: intermediate 10965 10966 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10967 @*/ 10968 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10969 { 10970 MatTransposeColoring matcolor = *c; 10971 10972 PetscFunctionBegin; 10973 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10974 if (--((PetscObject)matcolor)->refct > 0) { 10975 matcolor = NULL; 10976 PetscFunctionReturn(PETSC_SUCCESS); 10977 } 10978 10979 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10980 PetscCall(PetscFree(matcolor->rows)); 10981 PetscCall(PetscFree(matcolor->den2sp)); 10982 PetscCall(PetscFree(matcolor->colorforcol)); 10983 PetscCall(PetscFree(matcolor->columns)); 10984 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10985 PetscCall(PetscHeaderDestroy(c)); 10986 PetscFunctionReturn(PETSC_SUCCESS); 10987 } 10988 10989 /*@ 10990 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10991 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10992 `MatTransposeColoring` to sparse `B`. 10993 10994 Collective 10995 10996 Input Parameters: 10997 + coloring - coloring context created with `MatTransposeColoringCreate()` 10998 - B - sparse matrix 10999 11000 Output Parameter: 11001 . Btdense - dense matrix $B^T$ 11002 11003 Level: developer 11004 11005 Note: 11006 These are used internally for some implementations of `MatRARt()` 11007 11008 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 11009 @*/ 11010 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 11011 { 11012 PetscFunctionBegin; 11013 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11014 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 11015 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 11016 11017 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 11018 PetscFunctionReturn(PETSC_SUCCESS); 11019 } 11020 11021 /*@ 11022 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 11023 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 11024 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 11025 $C_{sp}$ from $C_{den}$. 11026 11027 Collective 11028 11029 Input Parameters: 11030 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 11031 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 11032 11033 Output Parameter: 11034 . Csp - sparse matrix 11035 11036 Level: developer 11037 11038 Note: 11039 These are used internally for some implementations of `MatRARt()` 11040 11041 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11042 @*/ 11043 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11044 { 11045 PetscFunctionBegin; 11046 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11047 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11048 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11049 11050 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11051 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11052 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11053 PetscFunctionReturn(PETSC_SUCCESS); 11054 } 11055 11056 /*@ 11057 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11058 11059 Collective 11060 11061 Input Parameters: 11062 + mat - the matrix product C 11063 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11064 11065 Output Parameter: 11066 . color - the new coloring context 11067 11068 Level: intermediate 11069 11070 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11071 `MatTransColoringApplyDenToSp()` 11072 @*/ 11073 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11074 { 11075 MatTransposeColoring c; 11076 MPI_Comm comm; 11077 11078 PetscFunctionBegin; 11079 PetscAssertPointer(color, 3); 11080 11081 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11082 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11083 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11084 c->ctype = iscoloring->ctype; 11085 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11086 *color = c; 11087 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11088 PetscFunctionReturn(PETSC_SUCCESS); 11089 } 11090 11091 /*@ 11092 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11093 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11094 11095 Not Collective 11096 11097 Input Parameter: 11098 . mat - the matrix 11099 11100 Output Parameter: 11101 . state - the current state 11102 11103 Level: intermediate 11104 11105 Notes: 11106 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11107 different matrices 11108 11109 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11110 11111 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11112 11113 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11114 @*/ 11115 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11116 { 11117 PetscFunctionBegin; 11118 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11119 *state = mat->nonzerostate; 11120 PetscFunctionReturn(PETSC_SUCCESS); 11121 } 11122 11123 /*@ 11124 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11125 matrices from each processor 11126 11127 Collective 11128 11129 Input Parameters: 11130 + comm - the communicators the parallel matrix will live on 11131 . seqmat - the input sequential matrices 11132 . n - number of local columns (or `PETSC_DECIDE`) 11133 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11134 11135 Output Parameter: 11136 . mpimat - the parallel matrix generated 11137 11138 Level: developer 11139 11140 Note: 11141 The number of columns of the matrix in EACH processor MUST be the same. 11142 11143 .seealso: [](ch_matrices), `Mat` 11144 @*/ 11145 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11146 { 11147 PetscMPIInt size; 11148 11149 PetscFunctionBegin; 11150 PetscCallMPI(MPI_Comm_size(comm, &size)); 11151 if (size == 1) { 11152 if (reuse == MAT_INITIAL_MATRIX) { 11153 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11154 } else { 11155 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11156 } 11157 PetscFunctionReturn(PETSC_SUCCESS); 11158 } 11159 11160 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"); 11161 11162 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11163 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11164 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11165 PetscFunctionReturn(PETSC_SUCCESS); 11166 } 11167 11168 /*@ 11169 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11170 11171 Collective 11172 11173 Input Parameters: 11174 + A - the matrix to create subdomains from 11175 - N - requested number of subdomains 11176 11177 Output Parameters: 11178 + n - number of subdomains resulting on this MPI process 11179 - iss - `IS` list with indices of subdomains on this MPI process 11180 11181 Level: advanced 11182 11183 Note: 11184 The number of subdomains must be smaller than the communicator size 11185 11186 .seealso: [](ch_matrices), `Mat`, `IS` 11187 @*/ 11188 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11189 { 11190 MPI_Comm comm, subcomm; 11191 PetscMPIInt size, rank, color; 11192 PetscInt rstart, rend, k; 11193 11194 PetscFunctionBegin; 11195 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11196 PetscCallMPI(MPI_Comm_size(comm, &size)); 11197 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11198 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); 11199 *n = 1; 11200 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11201 color = rank / k; 11202 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11203 PetscCall(PetscMalloc1(1, iss)); 11204 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11205 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11206 PetscCallMPI(MPI_Comm_free(&subcomm)); 11207 PetscFunctionReturn(PETSC_SUCCESS); 11208 } 11209 11210 /*@ 11211 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11212 11213 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11214 If they are not the same, uses `MatMatMatMult()`. 11215 11216 Once the coarse grid problem is constructed, correct for interpolation operators 11217 that are not of full rank, which can legitimately happen in the case of non-nested 11218 geometric multigrid. 11219 11220 Input Parameters: 11221 + restrct - restriction operator 11222 . dA - fine grid matrix 11223 . interpolate - interpolation operator 11224 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11225 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11226 11227 Output Parameter: 11228 . A - the Galerkin coarse matrix 11229 11230 Options Database Key: 11231 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11232 11233 Level: developer 11234 11235 Note: 11236 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11237 11238 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11239 @*/ 11240 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11241 { 11242 IS zerorows; 11243 Vec diag; 11244 11245 PetscFunctionBegin; 11246 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11247 /* Construct the coarse grid matrix */ 11248 if (interpolate == restrct) { 11249 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11250 } else { 11251 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11252 } 11253 11254 /* If the interpolation matrix is not of full rank, A will have zero rows. 11255 This can legitimately happen in the case of non-nested geometric multigrid. 11256 In that event, we set the rows of the matrix to the rows of the identity, 11257 ignoring the equations (as the RHS will also be zero). */ 11258 11259 PetscCall(MatFindZeroRows(*A, &zerorows)); 11260 11261 if (zerorows != NULL) { /* if there are any zero rows */ 11262 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11263 PetscCall(MatGetDiagonal(*A, diag)); 11264 PetscCall(VecISSet(diag, zerorows, 1.0)); 11265 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11266 PetscCall(VecDestroy(&diag)); 11267 PetscCall(ISDestroy(&zerorows)); 11268 } 11269 PetscFunctionReturn(PETSC_SUCCESS); 11270 } 11271 11272 /*@C 11273 MatSetOperation - Allows user to set a matrix operation for any matrix type 11274 11275 Logically Collective 11276 11277 Input Parameters: 11278 + mat - the matrix 11279 . op - the name of the operation 11280 - f - the function that provides the operation 11281 11282 Level: developer 11283 11284 Example Usage: 11285 .vb 11286 extern PetscErrorCode usermult(Mat, Vec, Vec); 11287 11288 PetscCall(MatCreateXXX(comm, ..., &A)); 11289 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11290 .ve 11291 11292 Notes: 11293 See the file `include/petscmat.h` for a complete list of matrix 11294 operations, which all have the form MATOP_<OPERATION>, where 11295 <OPERATION> is the name (in all capital letters) of the 11296 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11297 11298 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11299 sequence as the usual matrix interface routines, since they 11300 are intended to be accessed via the usual matrix interface 11301 routines, e.g., 11302 .vb 11303 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11304 .ve 11305 11306 In particular each function MUST return `PETSC_SUCCESS` on success and 11307 nonzero on failure. 11308 11309 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11310 11311 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11312 @*/ 11313 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11314 { 11315 PetscFunctionBegin; 11316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11317 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11318 (((void (**)(void))mat->ops)[op]) = f; 11319 PetscFunctionReturn(PETSC_SUCCESS); 11320 } 11321 11322 /*@C 11323 MatGetOperation - Gets a matrix operation for any matrix type. 11324 11325 Not Collective 11326 11327 Input Parameters: 11328 + mat - the matrix 11329 - op - the name of the operation 11330 11331 Output Parameter: 11332 . f - the function that provides the operation 11333 11334 Level: developer 11335 11336 Example Usage: 11337 .vb 11338 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11339 11340 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11341 .ve 11342 11343 Notes: 11344 See the file include/petscmat.h for a complete list of matrix 11345 operations, which all have the form MATOP_<OPERATION>, where 11346 <OPERATION> is the name (in all capital letters) of the 11347 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11348 11349 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11350 11351 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11352 @*/ 11353 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11354 { 11355 PetscFunctionBegin; 11356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11357 *f = (((void (**)(void))mat->ops)[op]); 11358 PetscFunctionReturn(PETSC_SUCCESS); 11359 } 11360 11361 /*@ 11362 MatHasOperation - Determines whether the given matrix supports the particular operation. 11363 11364 Not Collective 11365 11366 Input Parameters: 11367 + mat - the matrix 11368 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11369 11370 Output Parameter: 11371 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11372 11373 Level: advanced 11374 11375 Note: 11376 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11377 11378 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11379 @*/ 11380 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11381 { 11382 PetscFunctionBegin; 11383 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11384 PetscAssertPointer(has, 3); 11385 if (mat->ops->hasoperation) { 11386 PetscUseTypeMethod(mat, hasoperation, op, has); 11387 } else { 11388 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11389 else { 11390 *has = PETSC_FALSE; 11391 if (op == MATOP_CREATE_SUBMATRIX) { 11392 PetscMPIInt size; 11393 11394 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11395 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11396 } 11397 } 11398 } 11399 PetscFunctionReturn(PETSC_SUCCESS); 11400 } 11401 11402 /*@ 11403 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11404 11405 Collective 11406 11407 Input Parameter: 11408 . mat - the matrix 11409 11410 Output Parameter: 11411 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11412 11413 Level: beginner 11414 11415 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11416 @*/ 11417 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11418 { 11419 PetscFunctionBegin; 11420 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11421 PetscValidType(mat, 1); 11422 PetscAssertPointer(cong, 2); 11423 if (!mat->rmap || !mat->cmap) { 11424 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11425 PetscFunctionReturn(PETSC_SUCCESS); 11426 } 11427 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11428 PetscCall(PetscLayoutSetUp(mat->rmap)); 11429 PetscCall(PetscLayoutSetUp(mat->cmap)); 11430 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11431 if (*cong) mat->congruentlayouts = 1; 11432 else mat->congruentlayouts = 0; 11433 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11434 PetscFunctionReturn(PETSC_SUCCESS); 11435 } 11436 11437 PetscErrorCode MatSetInf(Mat A) 11438 { 11439 PetscFunctionBegin; 11440 PetscUseTypeMethod(A, setinf); 11441 PetscFunctionReturn(PETSC_SUCCESS); 11442 } 11443 11444 /*@ 11445 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 11446 and possibly removes small values from the graph structure. 11447 11448 Collective 11449 11450 Input Parameters: 11451 + A - the matrix 11452 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11453 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11454 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11455 . num_idx - size of 'index' array 11456 - index - array of block indices to use for graph strength of connection weight 11457 11458 Output Parameter: 11459 . graph - the resulting graph 11460 11461 Level: advanced 11462 11463 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11464 @*/ 11465 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11466 { 11467 PetscFunctionBegin; 11468 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11469 PetscValidType(A, 1); 11470 PetscValidLogicalCollectiveBool(A, scale, 3); 11471 PetscAssertPointer(graph, 7); 11472 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11473 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11474 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11475 PetscFunctionReturn(PETSC_SUCCESS); 11476 } 11477 11478 /*@ 11479 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11480 meaning the same memory is used for the matrix, and no new memory is allocated. 11481 11482 Collective 11483 11484 Input Parameters: 11485 + A - the matrix 11486 - 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 11487 11488 Level: intermediate 11489 11490 Developer Note: 11491 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11492 of the arrays in the data structure are unneeded. 11493 11494 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11495 @*/ 11496 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11497 { 11498 PetscFunctionBegin; 11499 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11500 PetscUseTypeMethod(A, eliminatezeros, keep); 11501 PetscFunctionReturn(PETSC_SUCCESS); 11502 } 11503