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 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 966 967 Collective 968 969 Input Parameter: 970 . A - the matrix 971 972 Level: intermediate 973 974 Notes: 975 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 976 977 Currently only supported for `MATAIJ` matrices. 978 979 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 980 @*/ 981 PetscErrorCode MatResetHash(Mat A) 982 { 983 PetscFunctionBegin; 984 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 985 PetscValidType(A, 1); 986 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 987 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 988 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 989 /* These flags are used to determine whether certain setups occur */ 990 A->was_assembled = PETSC_FALSE; 991 A->assembled = PETSC_FALSE; 992 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 993 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 994 PetscFunctionReturn(PETSC_SUCCESS); 995 } 996 997 /*@ 998 MatSetUp - Sets up the internal matrix data structures for later use. 999 1000 Collective 1001 1002 Input Parameter: 1003 . A - the matrix 1004 1005 Level: intermediate 1006 1007 Notes: 1008 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1009 setting values in the matrix. 1010 1011 This routine is called internally by other matrix functions when needed so rarely needs to be called by users 1012 1013 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1014 @*/ 1015 PetscErrorCode MatSetUp(Mat A) 1016 { 1017 PetscFunctionBegin; 1018 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1019 if (!((PetscObject)A)->type_name) { 1020 PetscMPIInt size; 1021 1022 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1023 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1024 } 1025 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1026 PetscCall(PetscLayoutSetUp(A->rmap)); 1027 PetscCall(PetscLayoutSetUp(A->cmap)); 1028 A->preallocated = PETSC_TRUE; 1029 PetscFunctionReturn(PETSC_SUCCESS); 1030 } 1031 1032 #if defined(PETSC_HAVE_SAWS) 1033 #include <petscviewersaws.h> 1034 #endif 1035 1036 /* 1037 If threadsafety is on extraneous matrices may be printed 1038 1039 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1040 */ 1041 #if !defined(PETSC_HAVE_THREADSAFETY) 1042 static PetscInt insidematview = 0; 1043 #endif 1044 1045 /*@ 1046 MatViewFromOptions - View properties of the matrix based on options set in the options database 1047 1048 Collective 1049 1050 Input Parameters: 1051 + A - the matrix 1052 . obj - optional additional object that provides the options prefix to use 1053 - name - command line option 1054 1055 Options Database Key: 1056 . -mat_view [viewertype]:... - the viewer and its options 1057 1058 Level: intermediate 1059 1060 Note: 1061 .vb 1062 If no value is provided ascii:stdout is used 1063 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1064 for example ascii::ascii_info prints just the information about the object not all details 1065 unless :append is given filename opens in write mode, overwriting what was already there 1066 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1067 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1068 socket[:port] defaults to the standard output port 1069 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1070 .ve 1071 1072 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1073 @*/ 1074 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1075 { 1076 PetscFunctionBegin; 1077 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1078 #if !defined(PETSC_HAVE_THREADSAFETY) 1079 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1080 #endif 1081 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1082 PetscFunctionReturn(PETSC_SUCCESS); 1083 } 1084 1085 /*@ 1086 MatView - display information about a matrix in a variety ways 1087 1088 Collective on viewer 1089 1090 Input Parameters: 1091 + mat - the matrix 1092 - viewer - visualization context 1093 1094 Options Database Keys: 1095 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1096 . -mat_view ::ascii_info_detail - Prints more detailed info 1097 . -mat_view - Prints matrix in ASCII format 1098 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1099 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1100 . -display <name> - Sets display name (default is host) 1101 . -draw_pause <sec> - Sets number of seconds to pause after display 1102 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1103 . -viewer_socket_machine <machine> - - 1104 . -viewer_socket_port <port> - - 1105 . -mat_view binary - save matrix to file in binary format 1106 - -viewer_binary_filename <name> - - 1107 1108 Level: beginner 1109 1110 Notes: 1111 The available visualization contexts include 1112 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1113 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1114 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1115 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1116 1117 The user can open alternative visualization contexts with 1118 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1119 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a 1120 specified file; corresponding input uses `MatLoad()` 1121 . `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to 1122 an X window display 1123 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer. 1124 Currently only the `MATSEQDENSE` and `MATAIJ` 1125 matrix types support the Socket viewer. 1126 1127 The user can call `PetscViewerPushFormat()` to specify the output 1128 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1129 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1130 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1131 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1132 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1133 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse 1134 format common among all matrix types 1135 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific 1136 format (which is in many cases the same as the default) 1137 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix 1138 size and structure (not the matrix entries) 1139 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about 1140 the matrix structure (still not vector or matrix entries) 1141 1142 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1143 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1144 1145 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1146 1147 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1148 viewer is used. 1149 1150 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1151 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1152 1153 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1154 and then use the following mouse functions. 1155 .vb 1156 left mouse: zoom in 1157 middle mouse: zoom out 1158 right mouse: continue with the simulation 1159 .ve 1160 1161 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1162 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1163 @*/ 1164 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1165 { 1166 PetscInt rows, cols, rbs, cbs; 1167 PetscBool isascii, isstring, issaws; 1168 PetscViewerFormat format; 1169 PetscMPIInt size; 1170 1171 PetscFunctionBegin; 1172 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1173 PetscValidType(mat, 1); 1174 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1175 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1176 1177 PetscCall(PetscViewerGetFormat(viewer, &format)); 1178 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1179 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1180 1181 #if !defined(PETSC_HAVE_THREADSAFETY) 1182 insidematview++; 1183 #endif 1184 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1185 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1186 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1187 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"); 1188 1189 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1190 if (isascii) { 1191 if (!mat->preallocated) { 1192 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1193 #if !defined(PETSC_HAVE_THREADSAFETY) 1194 insidematview--; 1195 #endif 1196 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1197 PetscFunctionReturn(PETSC_SUCCESS); 1198 } 1199 if (!mat->assembled) { 1200 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1201 #if !defined(PETSC_HAVE_THREADSAFETY) 1202 insidematview--; 1203 #endif 1204 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1205 PetscFunctionReturn(PETSC_SUCCESS); 1206 } 1207 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1208 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1209 MatNullSpace nullsp, transnullsp; 1210 1211 PetscCall(PetscViewerASCIIPushTab(viewer)); 1212 PetscCall(MatGetSize(mat, &rows, &cols)); 1213 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1214 if (rbs != 1 || cbs != 1) { 1215 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" : "")); 1216 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1217 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1218 if (mat->factortype) { 1219 MatSolverType solver; 1220 PetscCall(MatFactorGetSolverType(mat, &solver)); 1221 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1222 } 1223 if (mat->ops->getinfo) { 1224 MatInfo info; 1225 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1226 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1227 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1228 } 1229 PetscCall(MatGetNullSpace(mat, &nullsp)); 1230 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1231 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1232 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1233 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1234 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1235 PetscCall(PetscViewerASCIIPushTab(viewer)); 1236 PetscCall(MatProductView(mat, viewer)); 1237 PetscCall(PetscViewerASCIIPopTab(viewer)); 1238 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1239 IS tmp; 1240 1241 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1242 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1243 PetscCall(PetscViewerASCIIPushTab(viewer)); 1244 PetscCall(ISView(tmp, viewer)); 1245 PetscCall(PetscViewerASCIIPopTab(viewer)); 1246 PetscCall(ISDestroy(&tmp)); 1247 } 1248 } 1249 } else if (issaws) { 1250 #if defined(PETSC_HAVE_SAWS) 1251 PetscMPIInt rank; 1252 1253 PetscCall(PetscObjectName((PetscObject)mat)); 1254 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1255 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1256 #endif 1257 } else if (isstring) { 1258 const char *type; 1259 PetscCall(MatGetType(mat, &type)); 1260 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1261 PetscTryTypeMethod(mat, view, viewer); 1262 } 1263 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1264 PetscCall(PetscViewerASCIIPushTab(viewer)); 1265 PetscUseTypeMethod(mat, viewnative, viewer); 1266 PetscCall(PetscViewerASCIIPopTab(viewer)); 1267 } else if (mat->ops->view) { 1268 PetscCall(PetscViewerASCIIPushTab(viewer)); 1269 PetscUseTypeMethod(mat, view, viewer); 1270 PetscCall(PetscViewerASCIIPopTab(viewer)); 1271 } 1272 if (isascii) { 1273 PetscCall(PetscViewerGetFormat(viewer, &format)); 1274 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1275 } 1276 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1277 #if !defined(PETSC_HAVE_THREADSAFETY) 1278 insidematview--; 1279 #endif 1280 PetscFunctionReturn(PETSC_SUCCESS); 1281 } 1282 1283 #if defined(PETSC_USE_DEBUG) 1284 #include <../src/sys/totalview/tv_data_display.h> 1285 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1286 { 1287 TV_add_row("Local rows", "int", &mat->rmap->n); 1288 TV_add_row("Local columns", "int", &mat->cmap->n); 1289 TV_add_row("Global rows", "int", &mat->rmap->N); 1290 TV_add_row("Global columns", "int", &mat->cmap->N); 1291 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1292 return TV_format_OK; 1293 } 1294 #endif 1295 1296 /*@ 1297 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1298 with `MatView()`. The matrix format is determined from the options database. 1299 Generates a parallel MPI matrix if the communicator has more than one 1300 processor. The default matrix type is `MATAIJ`. 1301 1302 Collective 1303 1304 Input Parameters: 1305 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1306 or some related function before a call to `MatLoad()` 1307 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1308 1309 Options Database Key: 1310 . -matload_block_size <bs> - set block size 1311 1312 Level: beginner 1313 1314 Notes: 1315 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1316 `Mat` before calling this routine if you wish to set it from the options database. 1317 1318 `MatLoad()` automatically loads into the options database any options 1319 given in the file filename.info where filename is the name of the file 1320 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1321 file will be ignored if you use the -viewer_binary_skip_info option. 1322 1323 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1324 sets the default matrix type AIJ and sets the local and global sizes. 1325 If type and/or size is already set, then the same are used. 1326 1327 In parallel, each processor can load a subset of rows (or the 1328 entire matrix). This routine is especially useful when a large 1329 matrix is stored on disk and only part of it is desired on each 1330 processor. For example, a parallel solver may access only some of 1331 the rows from each processor. The algorithm used here reads 1332 relatively small blocks of data rather than reading the entire 1333 matrix and then subsetting it. 1334 1335 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1336 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1337 or the sequence like 1338 .vb 1339 `PetscViewer` v; 1340 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1341 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1342 `PetscViewerSetFromOptions`(v); 1343 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1344 `PetscViewerFileSetName`(v,"datafile"); 1345 .ve 1346 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1347 $ -viewer_type {binary, hdf5} 1348 1349 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1350 and src/mat/tutorials/ex10.c with the second approach. 1351 1352 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1353 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1354 Multiple objects, both matrices and vectors, can be stored within the same file. 1355 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1356 1357 Most users should not need to know the details of the binary storage 1358 format, since `MatLoad()` and `MatView()` completely hide these details. 1359 But for anyone who is interested, the standard binary matrix storage 1360 format is 1361 1362 .vb 1363 PetscInt MAT_FILE_CLASSID 1364 PetscInt number of rows 1365 PetscInt number of columns 1366 PetscInt total number of nonzeros 1367 PetscInt *number nonzeros in each row 1368 PetscInt *column indices of all nonzeros (starting index is zero) 1369 PetscScalar *values of all nonzeros 1370 .ve 1371 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1372 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 1373 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1374 1375 PETSc automatically does the byte swapping for 1376 machines that store the bytes reversed. Thus if you write your own binary 1377 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1378 and `PetscBinaryWrite()` to see how this may be done. 1379 1380 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1381 Each processor's chunk is loaded independently by its owning MPI process. 1382 Multiple objects, both matrices and vectors, can be stored within the same file. 1383 They are looked up by their PetscObject name. 1384 1385 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1386 by default the same structure and naming of the AIJ arrays and column count 1387 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1388 $ save example.mat A b -v7.3 1389 can be directly read by this routine (see Reference 1 for details). 1390 1391 Depending on your MATLAB version, this format might be a default, 1392 otherwise you can set it as default in Preferences. 1393 1394 Unless -nocompression flag is used to save the file in MATLAB, 1395 PETSc must be configured with ZLIB package. 1396 1397 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1398 1399 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1400 1401 Corresponding `MatView()` is not yet implemented. 1402 1403 The loaded matrix is actually a transpose of the original one in MATLAB, 1404 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1405 With this format, matrix is automatically transposed by PETSc, 1406 unless the matrix is marked as SPD or symmetric 1407 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1408 1409 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1410 1411 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1412 @*/ 1413 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1414 { 1415 PetscBool flg; 1416 1417 PetscFunctionBegin; 1418 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1419 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1420 1421 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1422 1423 flg = PETSC_FALSE; 1424 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1425 if (flg) { 1426 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1427 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1428 } 1429 flg = PETSC_FALSE; 1430 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1431 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1432 1433 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1434 PetscUseTypeMethod(mat, load, viewer); 1435 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1436 PetscFunctionReturn(PETSC_SUCCESS); 1437 } 1438 1439 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1440 { 1441 Mat_Redundant *redund = *redundant; 1442 1443 PetscFunctionBegin; 1444 if (redund) { 1445 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1446 PetscCall(ISDestroy(&redund->isrow)); 1447 PetscCall(ISDestroy(&redund->iscol)); 1448 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1449 } else { 1450 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1451 PetscCall(PetscFree(redund->sbuf_j)); 1452 PetscCall(PetscFree(redund->sbuf_a)); 1453 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1454 PetscCall(PetscFree(redund->rbuf_j[i])); 1455 PetscCall(PetscFree(redund->rbuf_a[i])); 1456 } 1457 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1458 } 1459 1460 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1461 PetscCall(PetscFree(redund)); 1462 } 1463 PetscFunctionReturn(PETSC_SUCCESS); 1464 } 1465 1466 /*@ 1467 MatDestroy - Frees space taken by a matrix. 1468 1469 Collective 1470 1471 Input Parameter: 1472 . A - the matrix 1473 1474 Level: beginner 1475 1476 Developer Note: 1477 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1478 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1479 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1480 if changes are needed here. 1481 1482 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1483 @*/ 1484 PetscErrorCode MatDestroy(Mat *A) 1485 { 1486 PetscFunctionBegin; 1487 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1488 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1489 if (--((PetscObject)*A)->refct > 0) { 1490 *A = NULL; 1491 PetscFunctionReturn(PETSC_SUCCESS); 1492 } 1493 1494 /* if memory was published with SAWs then destroy it */ 1495 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1496 PetscTryTypeMethod(*A, destroy); 1497 1498 PetscCall(PetscFree((*A)->factorprefix)); 1499 PetscCall(PetscFree((*A)->defaultvectype)); 1500 PetscCall(PetscFree((*A)->defaultrandtype)); 1501 PetscCall(PetscFree((*A)->bsizes)); 1502 PetscCall(PetscFree((*A)->solvertype)); 1503 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1504 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1505 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1506 PetscCall(MatProductClear(*A)); 1507 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1508 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1509 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1510 PetscCall(MatDestroy(&(*A)->schur)); 1511 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1512 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1513 PetscCall(PetscHeaderDestroy(A)); 1514 PetscFunctionReturn(PETSC_SUCCESS); 1515 } 1516 1517 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1518 /*@ 1519 MatSetValues - Inserts or adds a block of values into a matrix. 1520 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1521 MUST be called after all calls to `MatSetValues()` have been completed. 1522 1523 Not Collective 1524 1525 Input Parameters: 1526 + mat - the matrix 1527 . v - a logically two-dimensional array of values 1528 . m - the number of rows 1529 . idxm - the global indices of the rows 1530 . n - the number of columns 1531 . idxn - the global indices of the columns 1532 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1533 1534 Level: beginner 1535 1536 Notes: 1537 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1538 1539 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1540 options cannot be mixed without intervening calls to the assembly 1541 routines. 1542 1543 `MatSetValues()` uses 0-based row and column numbers in Fortran 1544 as well as in C. 1545 1546 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1547 simply ignored. This allows easily inserting element stiffness matrices 1548 with homogeneous Dirichlet boundary conditions that you don't want represented 1549 in the matrix. 1550 1551 Efficiency Alert: 1552 The routine `MatSetValuesBlocked()` may offer much better efficiency 1553 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1554 1555 Fortran Notes: 1556 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1557 .vb 1558 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1559 .ve 1560 1561 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1562 1563 Developer Note: 1564 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1565 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1566 1567 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1568 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1569 @*/ 1570 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1571 { 1572 PetscFunctionBeginHot; 1573 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1574 PetscValidType(mat, 1); 1575 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1576 PetscAssertPointer(idxm, 3); 1577 PetscAssertPointer(idxn, 5); 1578 MatCheckPreallocated(mat, 1); 1579 1580 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1581 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1582 1583 if (PetscDefined(USE_DEBUG)) { 1584 PetscInt i, j; 1585 1586 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1587 if (v) { 1588 for (i = 0; i < m; i++) { 1589 for (j = 0; j < n; j++) { 1590 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1591 #if defined(PETSC_USE_COMPLEX) 1592 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]); 1593 #else 1594 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]); 1595 #endif 1596 } 1597 } 1598 } 1599 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); 1600 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); 1601 } 1602 1603 if (mat->assembled) { 1604 mat->was_assembled = PETSC_TRUE; 1605 mat->assembled = PETSC_FALSE; 1606 } 1607 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1608 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1609 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1610 PetscFunctionReturn(PETSC_SUCCESS); 1611 } 1612 1613 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1614 /*@ 1615 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1616 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1617 MUST be called after all calls to `MatSetValues()` have been completed. 1618 1619 Not Collective 1620 1621 Input Parameters: 1622 + mat - the matrix 1623 . v - a logically two-dimensional array of values 1624 . ism - the rows to provide 1625 . isn - the columns to provide 1626 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1627 1628 Level: beginner 1629 1630 Notes: 1631 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1632 1633 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1634 options cannot be mixed without intervening calls to the assembly 1635 routines. 1636 1637 `MatSetValues()` uses 0-based row and column numbers in Fortran 1638 as well as in C. 1639 1640 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1641 simply ignored. This allows easily inserting element stiffness matrices 1642 with homogeneous Dirichlet boundary conditions that you don't want represented 1643 in the matrix. 1644 1645 Efficiency Alert: 1646 The routine `MatSetValuesBlocked()` may offer much better efficiency 1647 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1648 1649 This is currently not optimized for any particular `ISType` 1650 1651 Developer Note: 1652 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1653 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1654 1655 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1656 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1657 @*/ 1658 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1659 { 1660 PetscInt m, n; 1661 const PetscInt *rows, *cols; 1662 1663 PetscFunctionBeginHot; 1664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1665 PetscCall(ISGetIndices(ism, &rows)); 1666 PetscCall(ISGetIndices(isn, &cols)); 1667 PetscCall(ISGetLocalSize(ism, &m)); 1668 PetscCall(ISGetLocalSize(isn, &n)); 1669 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1670 PetscCall(ISRestoreIndices(ism, &rows)); 1671 PetscCall(ISRestoreIndices(isn, &cols)); 1672 PetscFunctionReturn(PETSC_SUCCESS); 1673 } 1674 1675 /*@ 1676 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1677 values into a matrix 1678 1679 Not Collective 1680 1681 Input Parameters: 1682 + mat - the matrix 1683 . row - the (block) row to set 1684 - v - a logically two-dimensional array of values 1685 1686 Level: intermediate 1687 1688 Notes: 1689 The values, `v`, are column-oriented (for the block version) and sorted 1690 1691 All the nonzero values in `row` must be provided 1692 1693 The matrix must have previously had its column indices set, likely by having been assembled. 1694 1695 `row` must belong to this MPI process 1696 1697 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1698 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1699 @*/ 1700 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1701 { 1702 PetscInt globalrow; 1703 1704 PetscFunctionBegin; 1705 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1706 PetscValidType(mat, 1); 1707 PetscAssertPointer(v, 3); 1708 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1709 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1710 PetscFunctionReturn(PETSC_SUCCESS); 1711 } 1712 1713 /*@ 1714 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1715 values into a matrix 1716 1717 Not Collective 1718 1719 Input Parameters: 1720 + mat - the matrix 1721 . row - the (block) row to set 1722 - 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 1723 1724 Level: advanced 1725 1726 Notes: 1727 The values, `v`, are column-oriented for the block version. 1728 1729 All the nonzeros in `row` must be provided 1730 1731 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1732 1733 `row` must belong to this process 1734 1735 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1736 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1737 @*/ 1738 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1739 { 1740 PetscFunctionBeginHot; 1741 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1742 PetscValidType(mat, 1); 1743 MatCheckPreallocated(mat, 1); 1744 PetscAssertPointer(v, 3); 1745 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1746 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1747 mat->insertmode = INSERT_VALUES; 1748 1749 if (mat->assembled) { 1750 mat->was_assembled = PETSC_TRUE; 1751 mat->assembled = PETSC_FALSE; 1752 } 1753 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1754 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1755 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1756 PetscFunctionReturn(PETSC_SUCCESS); 1757 } 1758 1759 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1760 /*@ 1761 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1762 Using structured grid indexing 1763 1764 Not Collective 1765 1766 Input Parameters: 1767 + mat - the matrix 1768 . m - number of rows being entered 1769 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1770 . n - number of columns being entered 1771 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1772 . v - a logically two-dimensional array of values 1773 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1774 1775 Level: beginner 1776 1777 Notes: 1778 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1779 1780 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1781 options cannot be mixed without intervening calls to the assembly 1782 routines. 1783 1784 The grid coordinates are across the entire grid, not just the local portion 1785 1786 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1787 as well as in C. 1788 1789 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1790 1791 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1792 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1793 1794 The columns and rows in the stencil passed in MUST be contained within the 1795 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1796 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1797 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1798 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1799 1800 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1801 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1802 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1803 `DM_BOUNDARY_PERIODIC` boundary type. 1804 1805 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 1806 a single value per point) you can skip filling those indices. 1807 1808 Inspired by the structured grid interface to the HYPRE package 1809 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1810 1811 Efficiency Alert: 1812 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1813 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1814 1815 Fortran Note: 1816 `idxm` and `idxn` should be declared as 1817 $ MatStencil idxm(4,m),idxn(4,n) 1818 and the values inserted using 1819 .vb 1820 idxm(MatStencil_i,1) = i 1821 idxm(MatStencil_j,1) = j 1822 idxm(MatStencil_k,1) = k 1823 idxm(MatStencil_c,1) = c 1824 etc 1825 .ve 1826 1827 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1828 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1829 @*/ 1830 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1831 { 1832 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1833 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1834 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1835 1836 PetscFunctionBegin; 1837 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1839 PetscValidType(mat, 1); 1840 PetscAssertPointer(idxm, 3); 1841 PetscAssertPointer(idxn, 5); 1842 1843 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1844 jdxm = buf; 1845 jdxn = buf + m; 1846 } else { 1847 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1848 jdxm = bufm; 1849 jdxn = bufn; 1850 } 1851 for (i = 0; i < m; i++) { 1852 for (j = 0; j < 3 - sdim; j++) dxm++; 1853 tmp = *dxm++ - starts[0]; 1854 for (j = 0; j < dim - 1; j++) { 1855 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1856 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1857 } 1858 if (mat->stencil.noc) dxm++; 1859 jdxm[i] = tmp; 1860 } 1861 for (i = 0; i < n; i++) { 1862 for (j = 0; j < 3 - sdim; j++) dxn++; 1863 tmp = *dxn++ - starts[0]; 1864 for (j = 0; j < dim - 1; j++) { 1865 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1866 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1867 } 1868 if (mat->stencil.noc) dxn++; 1869 jdxn[i] = tmp; 1870 } 1871 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1872 PetscCall(PetscFree2(bufm, bufn)); 1873 PetscFunctionReturn(PETSC_SUCCESS); 1874 } 1875 1876 /*@ 1877 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1878 Using structured grid indexing 1879 1880 Not Collective 1881 1882 Input Parameters: 1883 + mat - the matrix 1884 . m - number of rows being entered 1885 . idxm - grid coordinates for matrix rows being entered 1886 . n - number of columns being entered 1887 . idxn - grid coordinates for matrix columns being entered 1888 . v - a logically two-dimensional array of values 1889 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1890 1891 Level: beginner 1892 1893 Notes: 1894 By default the values, `v`, are row-oriented and unsorted. 1895 See `MatSetOption()` for other options. 1896 1897 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1898 options cannot be mixed without intervening calls to the assembly 1899 routines. 1900 1901 The grid coordinates are across the entire grid, not just the local portion 1902 1903 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1904 as well as in C. 1905 1906 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1907 1908 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1909 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1910 1911 The columns and rows in the stencil passed in MUST be contained within the 1912 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1913 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1914 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1915 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1916 1917 Negative indices may be passed in idxm and idxn, these rows and columns are 1918 simply ignored. This allows easily inserting element stiffness matrices 1919 with homogeneous Dirichlet boundary conditions that you don't want represented 1920 in the matrix. 1921 1922 Inspired by the structured grid interface to the HYPRE package 1923 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1924 1925 Fortran Note: 1926 `idxm` and `idxn` should be declared as 1927 $ MatStencil idxm(4,m),idxn(4,n) 1928 and the values inserted using 1929 .vb 1930 idxm(MatStencil_i,1) = i 1931 idxm(MatStencil_j,1) = j 1932 idxm(MatStencil_k,1) = k 1933 etc 1934 .ve 1935 1936 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1937 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1938 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1939 @*/ 1940 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1941 { 1942 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1943 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1944 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1945 1946 PetscFunctionBegin; 1947 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1948 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1949 PetscValidType(mat, 1); 1950 PetscAssertPointer(idxm, 3); 1951 PetscAssertPointer(idxn, 5); 1952 PetscAssertPointer(v, 6); 1953 1954 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1955 jdxm = buf; 1956 jdxn = buf + m; 1957 } else { 1958 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1959 jdxm = bufm; 1960 jdxn = bufn; 1961 } 1962 for (i = 0; i < m; i++) { 1963 for (j = 0; j < 3 - sdim; j++) dxm++; 1964 tmp = *dxm++ - starts[0]; 1965 for (j = 0; j < sdim - 1; j++) { 1966 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1967 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1968 } 1969 dxm++; 1970 jdxm[i] = tmp; 1971 } 1972 for (i = 0; i < n; i++) { 1973 for (j = 0; j < 3 - sdim; j++) dxn++; 1974 tmp = *dxn++ - starts[0]; 1975 for (j = 0; j < sdim - 1; j++) { 1976 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1977 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1978 } 1979 dxn++; 1980 jdxn[i] = tmp; 1981 } 1982 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1983 PetscCall(PetscFree2(bufm, bufn)); 1984 PetscFunctionReturn(PETSC_SUCCESS); 1985 } 1986 1987 /*@ 1988 MatSetStencil - Sets the grid information for setting values into a matrix via 1989 `MatSetValuesStencil()` 1990 1991 Not Collective 1992 1993 Input Parameters: 1994 + mat - the matrix 1995 . dim - dimension of the grid 1, 2, or 3 1996 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1997 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1998 - dof - number of degrees of freedom per node 1999 2000 Level: beginner 2001 2002 Notes: 2003 Inspired by the structured grid interface to the HYPRE package 2004 (www.llnl.gov/CASC/hyper) 2005 2006 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 2007 user. 2008 2009 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 2010 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 2011 @*/ 2012 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 2013 { 2014 PetscFunctionBegin; 2015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2016 PetscAssertPointer(dims, 3); 2017 PetscAssertPointer(starts, 4); 2018 2019 mat->stencil.dim = dim + (dof > 1); 2020 for (PetscInt i = 0; i < dim; i++) { 2021 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2022 mat->stencil.starts[i] = starts[dim - i - 1]; 2023 } 2024 mat->stencil.dims[dim] = dof; 2025 mat->stencil.starts[dim] = 0; 2026 mat->stencil.noc = (PetscBool)(dof == 1); 2027 PetscFunctionReturn(PETSC_SUCCESS); 2028 } 2029 2030 /*@ 2031 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2032 2033 Not Collective 2034 2035 Input Parameters: 2036 + mat - the matrix 2037 . v - a logically two-dimensional array of values 2038 . m - the number of block rows 2039 . idxm - the global block indices 2040 . n - the number of block columns 2041 . idxn - the global block indices 2042 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2043 2044 Level: intermediate 2045 2046 Notes: 2047 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2048 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2049 2050 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2051 NOT the total number of rows/columns; for example, if the block size is 2 and 2052 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2053 The values in `idxm` would be 1 2; that is the first index for each block divided by 2054 the block size. 2055 2056 You must call `MatSetBlockSize()` when constructing this matrix (before 2057 preallocating it). 2058 2059 By default the values, `v`, are row-oriented, so the layout of 2060 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2061 2062 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2063 options cannot be mixed without intervening calls to the assembly 2064 routines. 2065 2066 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2067 as well as in C. 2068 2069 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2070 simply ignored. This allows easily inserting element stiffness matrices 2071 with homogeneous Dirichlet boundary conditions that you don't want represented 2072 in the matrix. 2073 2074 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2075 internal searching must be done to determine where to place the 2076 data in the matrix storage space. By instead inserting blocks of 2077 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2078 reduced. 2079 2080 Example: 2081 .vb 2082 Suppose m=n=2 and block size(bs) = 2 The array is 2083 2084 1 2 | 3 4 2085 5 6 | 7 8 2086 - - - | - - - 2087 9 10 | 11 12 2088 13 14 | 15 16 2089 2090 v[] should be passed in like 2091 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2092 2093 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2094 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2095 .ve 2096 2097 Fortran Notes: 2098 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2099 .vb 2100 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2101 .ve 2102 2103 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2104 2105 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2106 @*/ 2107 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2108 { 2109 PetscFunctionBeginHot; 2110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2111 PetscValidType(mat, 1); 2112 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2113 PetscAssertPointer(idxm, 3); 2114 PetscAssertPointer(idxn, 5); 2115 MatCheckPreallocated(mat, 1); 2116 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2117 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2118 if (PetscDefined(USE_DEBUG)) { 2119 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2120 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2121 } 2122 if (PetscDefined(USE_DEBUG)) { 2123 PetscInt rbs, cbs, M, N, i; 2124 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2125 PetscCall(MatGetSize(mat, &M, &N)); 2126 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); 2127 for (i = 0; i < n; i++) 2128 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); 2129 } 2130 if (mat->assembled) { 2131 mat->was_assembled = PETSC_TRUE; 2132 mat->assembled = PETSC_FALSE; 2133 } 2134 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2135 if (mat->ops->setvaluesblocked) { 2136 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2137 } else { 2138 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2139 PetscInt i, j, bs, cbs; 2140 2141 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2142 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2143 iidxm = buf; 2144 iidxn = buf + m * bs; 2145 } else { 2146 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2147 iidxm = bufr; 2148 iidxn = bufc; 2149 } 2150 for (i = 0; i < m; i++) { 2151 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2152 } 2153 if (m != n || bs != cbs || idxm != idxn) { 2154 for (i = 0; i < n; i++) { 2155 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2156 } 2157 } else iidxn = iidxm; 2158 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2159 PetscCall(PetscFree2(bufr, bufc)); 2160 } 2161 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2162 PetscFunctionReturn(PETSC_SUCCESS); 2163 } 2164 2165 /*@ 2166 MatGetValues - Gets a block of local values from a matrix. 2167 2168 Not Collective; can only return values that are owned by the give process 2169 2170 Input Parameters: 2171 + mat - the matrix 2172 . v - a logically two-dimensional array for storing the values 2173 . m - the number of rows 2174 . idxm - the global indices of the rows 2175 . n - the number of columns 2176 - idxn - the global indices of the columns 2177 2178 Level: advanced 2179 2180 Notes: 2181 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2182 The values, `v`, are then returned in a row-oriented format, 2183 analogous to that used by default in `MatSetValues()`. 2184 2185 `MatGetValues()` uses 0-based row and column numbers in 2186 Fortran as well as in C. 2187 2188 `MatGetValues()` requires that the matrix has been assembled 2189 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2190 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2191 without intermediate matrix assembly. 2192 2193 Negative row or column indices will be ignored and those locations in `v` will be 2194 left unchanged. 2195 2196 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2197 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2198 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2199 2200 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2201 @*/ 2202 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2203 { 2204 PetscFunctionBegin; 2205 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2206 PetscValidType(mat, 1); 2207 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2208 PetscAssertPointer(idxm, 3); 2209 PetscAssertPointer(idxn, 5); 2210 PetscAssertPointer(v, 6); 2211 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2212 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2213 MatCheckPreallocated(mat, 1); 2214 2215 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2216 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2217 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2218 PetscFunctionReturn(PETSC_SUCCESS); 2219 } 2220 2221 /*@ 2222 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2223 defined previously by `MatSetLocalToGlobalMapping()` 2224 2225 Not Collective 2226 2227 Input Parameters: 2228 + mat - the matrix 2229 . nrow - number of rows 2230 . irow - the row local indices 2231 . ncol - number of columns 2232 - icol - the column local indices 2233 2234 Output Parameter: 2235 . y - a logically two-dimensional array of values 2236 2237 Level: advanced 2238 2239 Notes: 2240 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2241 2242 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, 2243 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2244 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2245 with `MatSetLocalToGlobalMapping()`. 2246 2247 Developer Note: 2248 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2249 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2250 2251 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2252 `MatSetValuesLocal()`, `MatGetValues()` 2253 @*/ 2254 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2255 { 2256 PetscFunctionBeginHot; 2257 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2258 PetscValidType(mat, 1); 2259 MatCheckPreallocated(mat, 1); 2260 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2261 PetscAssertPointer(irow, 3); 2262 PetscAssertPointer(icol, 5); 2263 if (PetscDefined(USE_DEBUG)) { 2264 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2265 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2266 } 2267 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2268 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2269 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2270 else { 2271 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2272 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2273 irowm = buf; 2274 icolm = buf + nrow; 2275 } else { 2276 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2277 irowm = bufr; 2278 icolm = bufc; 2279 } 2280 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2281 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2282 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2283 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2284 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2285 PetscCall(PetscFree2(bufr, bufc)); 2286 } 2287 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2288 PetscFunctionReturn(PETSC_SUCCESS); 2289 } 2290 2291 /*@ 2292 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2293 the same size. Currently, this can only be called once and creates the given matrix. 2294 2295 Not Collective 2296 2297 Input Parameters: 2298 + mat - the matrix 2299 . nb - the number of blocks 2300 . bs - the number of rows (and columns) in each block 2301 . rows - a concatenation of the rows for each block 2302 - v - a concatenation of logically two-dimensional arrays of values 2303 2304 Level: advanced 2305 2306 Notes: 2307 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2308 2309 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2310 2311 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2312 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2313 @*/ 2314 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2315 { 2316 PetscFunctionBegin; 2317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2318 PetscValidType(mat, 1); 2319 PetscAssertPointer(rows, 4); 2320 PetscAssertPointer(v, 5); 2321 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2322 2323 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2324 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2325 else { 2326 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2327 } 2328 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2329 PetscFunctionReturn(PETSC_SUCCESS); 2330 } 2331 2332 /*@ 2333 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2334 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2335 using a local (per-processor) numbering. 2336 2337 Not Collective 2338 2339 Input Parameters: 2340 + x - the matrix 2341 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2342 - cmapping - column mapping 2343 2344 Level: intermediate 2345 2346 Note: 2347 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2348 2349 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2350 @*/ 2351 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2352 { 2353 PetscFunctionBegin; 2354 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2355 PetscValidType(x, 1); 2356 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2357 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2358 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2359 else { 2360 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2361 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2362 } 2363 PetscFunctionReturn(PETSC_SUCCESS); 2364 } 2365 2366 /*@ 2367 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2368 2369 Not Collective 2370 2371 Input Parameter: 2372 . A - the matrix 2373 2374 Output Parameters: 2375 + rmapping - row mapping 2376 - cmapping - column mapping 2377 2378 Level: advanced 2379 2380 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2381 @*/ 2382 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2383 { 2384 PetscFunctionBegin; 2385 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2386 PetscValidType(A, 1); 2387 if (rmapping) { 2388 PetscAssertPointer(rmapping, 2); 2389 *rmapping = A->rmap->mapping; 2390 } 2391 if (cmapping) { 2392 PetscAssertPointer(cmapping, 3); 2393 *cmapping = A->cmap->mapping; 2394 } 2395 PetscFunctionReturn(PETSC_SUCCESS); 2396 } 2397 2398 /*@ 2399 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2400 2401 Logically Collective 2402 2403 Input Parameters: 2404 + A - the matrix 2405 . rmap - row layout 2406 - cmap - column layout 2407 2408 Level: advanced 2409 2410 Note: 2411 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2412 2413 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2414 @*/ 2415 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2419 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2420 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2421 PetscFunctionReturn(PETSC_SUCCESS); 2422 } 2423 2424 /*@ 2425 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2426 2427 Not Collective 2428 2429 Input Parameter: 2430 . A - the matrix 2431 2432 Output Parameters: 2433 + rmap - row layout 2434 - cmap - column layout 2435 2436 Level: advanced 2437 2438 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2439 @*/ 2440 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2441 { 2442 PetscFunctionBegin; 2443 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2444 PetscValidType(A, 1); 2445 if (rmap) { 2446 PetscAssertPointer(rmap, 2); 2447 *rmap = A->rmap; 2448 } 2449 if (cmap) { 2450 PetscAssertPointer(cmap, 3); 2451 *cmap = A->cmap; 2452 } 2453 PetscFunctionReturn(PETSC_SUCCESS); 2454 } 2455 2456 /*@ 2457 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2458 using a local numbering of the rows and columns. 2459 2460 Not Collective 2461 2462 Input Parameters: 2463 + mat - the matrix 2464 . nrow - number of rows 2465 . irow - the row local indices 2466 . ncol - number of columns 2467 . icol - the column local indices 2468 . y - a logically two-dimensional array of values 2469 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2470 2471 Level: intermediate 2472 2473 Notes: 2474 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2475 2476 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2477 options cannot be mixed without intervening calls to the assembly 2478 routines. 2479 2480 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2481 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2482 2483 Fortran Notes: 2484 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2485 .vb 2486 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2487 .ve 2488 2489 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2490 2491 Developer Note: 2492 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2493 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2494 2495 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2496 `MatGetValuesLocal()` 2497 @*/ 2498 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2499 { 2500 PetscFunctionBeginHot; 2501 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2502 PetscValidType(mat, 1); 2503 MatCheckPreallocated(mat, 1); 2504 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2505 PetscAssertPointer(irow, 3); 2506 PetscAssertPointer(icol, 5); 2507 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2508 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2509 if (PetscDefined(USE_DEBUG)) { 2510 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2511 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2512 } 2513 2514 if (mat->assembled) { 2515 mat->was_assembled = PETSC_TRUE; 2516 mat->assembled = PETSC_FALSE; 2517 } 2518 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2519 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2520 else { 2521 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2522 const PetscInt *irowm, *icolm; 2523 2524 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2525 bufr = buf; 2526 bufc = buf + nrow; 2527 irowm = bufr; 2528 icolm = bufc; 2529 } else { 2530 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2531 irowm = bufr; 2532 icolm = bufc; 2533 } 2534 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2535 else irowm = irow; 2536 if (mat->cmap->mapping) { 2537 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2538 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2539 } else icolm = irowm; 2540 } else icolm = icol; 2541 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2542 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2543 } 2544 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2545 PetscFunctionReturn(PETSC_SUCCESS); 2546 } 2547 2548 /*@ 2549 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2550 using a local ordering of the nodes a block at a time. 2551 2552 Not Collective 2553 2554 Input Parameters: 2555 + mat - the matrix 2556 . nrow - number of rows 2557 . irow - the row local indices 2558 . ncol - number of columns 2559 . icol - the column local indices 2560 . y - a logically two-dimensional array of values 2561 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2562 2563 Level: intermediate 2564 2565 Notes: 2566 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2567 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2568 2569 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2570 options cannot be mixed without intervening calls to the assembly 2571 routines. 2572 2573 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2574 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2575 2576 Fortran Notes: 2577 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2578 .vb 2579 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2580 .ve 2581 2582 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2583 2584 Developer Note: 2585 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2586 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2587 2588 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2589 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2590 @*/ 2591 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2592 { 2593 PetscFunctionBeginHot; 2594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2595 PetscValidType(mat, 1); 2596 MatCheckPreallocated(mat, 1); 2597 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2598 PetscAssertPointer(irow, 3); 2599 PetscAssertPointer(icol, 5); 2600 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2601 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2602 if (PetscDefined(USE_DEBUG)) { 2603 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2604 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); 2605 } 2606 2607 if (mat->assembled) { 2608 mat->was_assembled = PETSC_TRUE; 2609 mat->assembled = PETSC_FALSE; 2610 } 2611 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2612 PetscInt irbs, rbs; 2613 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2614 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2615 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2616 } 2617 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2618 PetscInt icbs, cbs; 2619 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2620 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2621 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2622 } 2623 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2624 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2625 else { 2626 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2627 const PetscInt *irowm, *icolm; 2628 2629 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2630 bufr = buf; 2631 bufc = buf + nrow; 2632 irowm = bufr; 2633 icolm = bufc; 2634 } else { 2635 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2636 irowm = bufr; 2637 icolm = bufc; 2638 } 2639 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2640 else irowm = irow; 2641 if (mat->cmap->mapping) { 2642 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2643 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2644 } else icolm = irowm; 2645 } else icolm = icol; 2646 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2647 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2648 } 2649 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2650 PetscFunctionReturn(PETSC_SUCCESS); 2651 } 2652 2653 /*@ 2654 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2655 2656 Collective 2657 2658 Input Parameters: 2659 + mat - the matrix 2660 - x - the vector to be multiplied 2661 2662 Output Parameter: 2663 . y - the result 2664 2665 Level: developer 2666 2667 Note: 2668 The vectors `x` and `y` cannot be the same. I.e., one cannot 2669 call `MatMultDiagonalBlock`(A,y,y). 2670 2671 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2672 @*/ 2673 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2674 { 2675 PetscFunctionBegin; 2676 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2677 PetscValidType(mat, 1); 2678 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2679 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2680 2681 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2682 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2683 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2684 MatCheckPreallocated(mat, 1); 2685 2686 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2687 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2688 PetscFunctionReturn(PETSC_SUCCESS); 2689 } 2690 2691 /*@ 2692 MatMult - Computes the matrix-vector product, $y = Ax$. 2693 2694 Neighbor-wise Collective 2695 2696 Input Parameters: 2697 + mat - the matrix 2698 - x - the vector to be multiplied 2699 2700 Output Parameter: 2701 . y - the result 2702 2703 Level: beginner 2704 2705 Note: 2706 The vectors `x` and `y` cannot be the same. I.e., one cannot 2707 call `MatMult`(A,y,y). 2708 2709 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2710 @*/ 2711 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2712 { 2713 PetscFunctionBegin; 2714 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2715 PetscValidType(mat, 1); 2716 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2717 VecCheckAssembled(x); 2718 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2719 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2720 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2721 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2722 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); 2723 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); 2724 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); 2725 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); 2726 PetscCall(VecSetErrorIfLocked(y, 3)); 2727 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2728 MatCheckPreallocated(mat, 1); 2729 2730 PetscCall(VecLockReadPush(x)); 2731 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2732 PetscUseTypeMethod(mat, mult, x, y); 2733 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2734 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2735 PetscCall(VecLockReadPop(x)); 2736 PetscFunctionReturn(PETSC_SUCCESS); 2737 } 2738 2739 /*@ 2740 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2741 2742 Neighbor-wise Collective 2743 2744 Input Parameters: 2745 + mat - the matrix 2746 - x - the vector to be multiplied 2747 2748 Output Parameter: 2749 . y - the result 2750 2751 Level: beginner 2752 2753 Notes: 2754 The vectors `x` and `y` cannot be the same. I.e., one cannot 2755 call `MatMultTranspose`(A,y,y). 2756 2757 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2758 use `MatMultHermitianTranspose()` 2759 2760 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2761 @*/ 2762 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2763 { 2764 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2765 2766 PetscFunctionBegin; 2767 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2768 PetscValidType(mat, 1); 2769 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2770 VecCheckAssembled(x); 2771 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2772 2773 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2774 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2775 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2776 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); 2777 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); 2778 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); 2779 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); 2780 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2781 MatCheckPreallocated(mat, 1); 2782 2783 if (!mat->ops->multtranspose) { 2784 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2785 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); 2786 } else op = mat->ops->multtranspose; 2787 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2788 PetscCall(VecLockReadPush(x)); 2789 PetscCall((*op)(mat, x, y)); 2790 PetscCall(VecLockReadPop(x)); 2791 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2792 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2793 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2794 PetscFunctionReturn(PETSC_SUCCESS); 2795 } 2796 2797 /*@ 2798 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2799 2800 Neighbor-wise Collective 2801 2802 Input Parameters: 2803 + mat - the matrix 2804 - x - the vector to be multiplied 2805 2806 Output Parameter: 2807 . y - the result 2808 2809 Level: beginner 2810 2811 Notes: 2812 The vectors `x` and `y` cannot be the same. I.e., one cannot 2813 call `MatMultHermitianTranspose`(A,y,y). 2814 2815 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2816 2817 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2818 2819 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2820 @*/ 2821 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2822 { 2823 PetscFunctionBegin; 2824 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2825 PetscValidType(mat, 1); 2826 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2827 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2828 2829 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2830 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2831 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2832 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); 2833 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); 2834 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); 2835 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); 2836 MatCheckPreallocated(mat, 1); 2837 2838 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2839 #if defined(PETSC_USE_COMPLEX) 2840 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2841 PetscCall(VecLockReadPush(x)); 2842 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2843 else PetscUseTypeMethod(mat, mult, x, y); 2844 PetscCall(VecLockReadPop(x)); 2845 } else { 2846 Vec w; 2847 PetscCall(VecDuplicate(x, &w)); 2848 PetscCall(VecCopy(x, w)); 2849 PetscCall(VecConjugate(w)); 2850 PetscCall(MatMultTranspose(mat, w, y)); 2851 PetscCall(VecDestroy(&w)); 2852 PetscCall(VecConjugate(y)); 2853 } 2854 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2855 #else 2856 PetscCall(MatMultTranspose(mat, x, y)); 2857 #endif 2858 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2859 PetscFunctionReturn(PETSC_SUCCESS); 2860 } 2861 2862 /*@ 2863 MatMultAdd - Computes $v3 = v2 + A * v1$. 2864 2865 Neighbor-wise Collective 2866 2867 Input Parameters: 2868 + mat - the matrix 2869 . v1 - the vector to be multiplied by `mat` 2870 - v2 - the vector to be added to the result 2871 2872 Output Parameter: 2873 . v3 - the result 2874 2875 Level: beginner 2876 2877 Note: 2878 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2879 call `MatMultAdd`(A,v1,v2,v1). 2880 2881 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2882 @*/ 2883 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2884 { 2885 PetscFunctionBegin; 2886 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2887 PetscValidType(mat, 1); 2888 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2889 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2890 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2891 2892 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2893 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2894 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); 2895 /* 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); 2896 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); */ 2897 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); 2898 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); 2899 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2900 MatCheckPreallocated(mat, 1); 2901 2902 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2903 PetscCall(VecLockReadPush(v1)); 2904 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2905 PetscCall(VecLockReadPop(v1)); 2906 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2907 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2908 PetscFunctionReturn(PETSC_SUCCESS); 2909 } 2910 2911 /*@ 2912 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2913 2914 Neighbor-wise Collective 2915 2916 Input Parameters: 2917 + mat - the matrix 2918 . v1 - the vector to be multiplied by the transpose of the matrix 2919 - v2 - the vector to be added to the result 2920 2921 Output Parameter: 2922 . v3 - the result 2923 2924 Level: beginner 2925 2926 Note: 2927 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2928 call `MatMultTransposeAdd`(A,v1,v2,v1). 2929 2930 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2931 @*/ 2932 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2933 { 2934 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2935 2936 PetscFunctionBegin; 2937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2938 PetscValidType(mat, 1); 2939 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2940 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2941 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2942 2943 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2944 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2945 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); 2946 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); 2947 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); 2948 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2949 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2950 MatCheckPreallocated(mat, 1); 2951 2952 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2953 PetscCall(VecLockReadPush(v1)); 2954 PetscCall((*op)(mat, v1, v2, v3)); 2955 PetscCall(VecLockReadPop(v1)); 2956 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2957 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2958 PetscFunctionReturn(PETSC_SUCCESS); 2959 } 2960 2961 /*@ 2962 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2963 2964 Neighbor-wise Collective 2965 2966 Input Parameters: 2967 + mat - the matrix 2968 . v1 - the vector to be multiplied by the Hermitian transpose 2969 - v2 - the vector to be added to the result 2970 2971 Output Parameter: 2972 . v3 - the result 2973 2974 Level: beginner 2975 2976 Note: 2977 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2978 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2979 2980 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2981 @*/ 2982 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2983 { 2984 PetscFunctionBegin; 2985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2986 PetscValidType(mat, 1); 2987 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2988 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2989 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2990 2991 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2992 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2993 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2994 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); 2995 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); 2996 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); 2997 MatCheckPreallocated(mat, 1); 2998 2999 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 3000 PetscCall(VecLockReadPush(v1)); 3001 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 3002 else { 3003 Vec w, z; 3004 PetscCall(VecDuplicate(v1, &w)); 3005 PetscCall(VecCopy(v1, w)); 3006 PetscCall(VecConjugate(w)); 3007 PetscCall(VecDuplicate(v3, &z)); 3008 PetscCall(MatMultTranspose(mat, w, z)); 3009 PetscCall(VecDestroy(&w)); 3010 PetscCall(VecConjugate(z)); 3011 if (v2 != v3) { 3012 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 3013 } else { 3014 PetscCall(VecAXPY(v3, 1.0, z)); 3015 } 3016 PetscCall(VecDestroy(&z)); 3017 } 3018 PetscCall(VecLockReadPop(v1)); 3019 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 3020 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 3021 PetscFunctionReturn(PETSC_SUCCESS); 3022 } 3023 3024 /*@ 3025 MatGetFactorType - gets the type of factorization a matrix is 3026 3027 Not Collective 3028 3029 Input Parameter: 3030 . mat - the matrix 3031 3032 Output Parameter: 3033 . 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` 3034 3035 Level: intermediate 3036 3037 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3038 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3039 @*/ 3040 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3041 { 3042 PetscFunctionBegin; 3043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3044 PetscValidType(mat, 1); 3045 PetscAssertPointer(t, 2); 3046 *t = mat->factortype; 3047 PetscFunctionReturn(PETSC_SUCCESS); 3048 } 3049 3050 /*@ 3051 MatSetFactorType - sets the type of factorization a matrix is 3052 3053 Logically Collective 3054 3055 Input Parameters: 3056 + mat - the matrix 3057 - 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` 3058 3059 Level: intermediate 3060 3061 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3062 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3063 @*/ 3064 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3065 { 3066 PetscFunctionBegin; 3067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3068 PetscValidType(mat, 1); 3069 mat->factortype = t; 3070 PetscFunctionReturn(PETSC_SUCCESS); 3071 } 3072 3073 /*@ 3074 MatGetInfo - Returns information about matrix storage (number of 3075 nonzeros, memory, etc.). 3076 3077 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3078 3079 Input Parameters: 3080 + mat - the matrix 3081 - 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) 3082 3083 Output Parameter: 3084 . info - matrix information context 3085 3086 Options Database Key: 3087 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3088 3089 Level: intermediate 3090 3091 Notes: 3092 The `MatInfo` context contains a variety of matrix data, including 3093 number of nonzeros allocated and used, number of mallocs during 3094 matrix assembly, etc. Additional information for factored matrices 3095 is provided (such as the fill ratio, number of mallocs during 3096 factorization, etc.). 3097 3098 Example: 3099 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3100 data within the `MatInfo` context. For example, 3101 .vb 3102 MatInfo info; 3103 Mat A; 3104 double mal, nz_a, nz_u; 3105 3106 MatGetInfo(A, MAT_LOCAL, &info); 3107 mal = info.mallocs; 3108 nz_a = info.nz_allocated; 3109 .ve 3110 3111 Fortran Note: 3112 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3113 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3114 a complete list of parameter names. 3115 .vb 3116 MatInfo info(MAT_INFO_SIZE) 3117 double precision mal, nz_a 3118 Mat A 3119 integer ierr 3120 3121 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3122 mal = info(MAT_INFO_MALLOCS) 3123 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3124 .ve 3125 3126 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3127 @*/ 3128 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3129 { 3130 PetscFunctionBegin; 3131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3132 PetscValidType(mat, 1); 3133 PetscAssertPointer(info, 3); 3134 MatCheckPreallocated(mat, 1); 3135 PetscUseTypeMethod(mat, getinfo, flag, info); 3136 PetscFunctionReturn(PETSC_SUCCESS); 3137 } 3138 3139 /* 3140 This is used by external packages where it is not easy to get the info from the actual 3141 matrix factorization. 3142 */ 3143 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3144 { 3145 PetscFunctionBegin; 3146 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3147 PetscFunctionReturn(PETSC_SUCCESS); 3148 } 3149 3150 /*@ 3151 MatLUFactor - Performs in-place LU factorization of matrix. 3152 3153 Collective 3154 3155 Input Parameters: 3156 + mat - the matrix 3157 . row - row permutation 3158 . col - column permutation 3159 - info - options for factorization, includes 3160 .vb 3161 fill - expected fill as ratio of original fill. 3162 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3163 Run with the option -info to determine an optimal value to use 3164 .ve 3165 3166 Level: developer 3167 3168 Notes: 3169 Most users should employ the `KSP` interface for linear solvers 3170 instead of working directly with matrix algebra routines such as this. 3171 See, e.g., `KSPCreate()`. 3172 3173 This changes the state of the matrix to a factored matrix; it cannot be used 3174 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3175 3176 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3177 when not using `KSP`. 3178 3179 Developer Note: 3180 The Fortran interface is not autogenerated as the 3181 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3182 3183 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3184 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3185 @*/ 3186 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3187 { 3188 MatFactorInfo tinfo; 3189 3190 PetscFunctionBegin; 3191 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3192 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3193 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3194 if (info) PetscAssertPointer(info, 4); 3195 PetscValidType(mat, 1); 3196 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3197 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3198 MatCheckPreallocated(mat, 1); 3199 if (!info) { 3200 PetscCall(MatFactorInfoInitialize(&tinfo)); 3201 info = &tinfo; 3202 } 3203 3204 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3205 PetscUseTypeMethod(mat, lufactor, row, col, info); 3206 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3207 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3208 PetscFunctionReturn(PETSC_SUCCESS); 3209 } 3210 3211 /*@ 3212 MatILUFactor - Performs in-place ILU factorization of matrix. 3213 3214 Collective 3215 3216 Input Parameters: 3217 + mat - the matrix 3218 . row - row permutation 3219 . col - column permutation 3220 - info - structure containing 3221 .vb 3222 levels - number of levels of fill. 3223 expected fill - as ratio of original fill. 3224 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3225 missing diagonal entries) 3226 .ve 3227 3228 Level: developer 3229 3230 Notes: 3231 Most users should employ the `KSP` interface for linear solvers 3232 instead of working directly with matrix algebra routines such as this. 3233 See, e.g., `KSPCreate()`. 3234 3235 Probably really in-place only when level of fill is zero, otherwise allocates 3236 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3237 when not using `KSP`. 3238 3239 Developer Note: 3240 The Fortran interface is not autogenerated as the 3241 interface definition cannot be generated correctly [due to MatFactorInfo] 3242 3243 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3244 @*/ 3245 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3246 { 3247 PetscFunctionBegin; 3248 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3249 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3250 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3251 PetscAssertPointer(info, 4); 3252 PetscValidType(mat, 1); 3253 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3254 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3255 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3256 MatCheckPreallocated(mat, 1); 3257 3258 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3259 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3260 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3261 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3262 PetscFunctionReturn(PETSC_SUCCESS); 3263 } 3264 3265 /*@ 3266 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3267 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3268 3269 Collective 3270 3271 Input Parameters: 3272 + fact - the factor matrix obtained with `MatGetFactor()` 3273 . mat - the matrix 3274 . row - the row permutation 3275 . col - the column permutation 3276 - info - options for factorization, includes 3277 .vb 3278 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3279 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3280 .ve 3281 3282 Level: developer 3283 3284 Notes: 3285 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3286 3287 Most users should employ the simplified `KSP` interface for linear solvers 3288 instead of working directly with matrix algebra routines such as this. 3289 See, e.g., `KSPCreate()`. 3290 3291 Developer Note: 3292 The Fortran interface is not autogenerated as the 3293 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3294 3295 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3296 @*/ 3297 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3298 { 3299 MatFactorInfo tinfo; 3300 3301 PetscFunctionBegin; 3302 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3303 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3304 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3305 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3306 if (info) PetscAssertPointer(info, 5); 3307 PetscValidType(fact, 1); 3308 PetscValidType(mat, 2); 3309 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3310 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3311 MatCheckPreallocated(mat, 2); 3312 if (!info) { 3313 PetscCall(MatFactorInfoInitialize(&tinfo)); 3314 info = &tinfo; 3315 } 3316 3317 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3318 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3319 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3320 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3321 PetscFunctionReturn(PETSC_SUCCESS); 3322 } 3323 3324 /*@ 3325 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3326 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3327 3328 Collective 3329 3330 Input Parameters: 3331 + fact - the factor matrix obtained with `MatGetFactor()` 3332 . mat - the matrix 3333 - info - options for factorization 3334 3335 Level: developer 3336 3337 Notes: 3338 See `MatLUFactor()` for in-place factorization. See 3339 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3340 3341 Most users should employ the `KSP` interface for linear solvers 3342 instead of working directly with matrix algebra routines such as this. 3343 See, e.g., `KSPCreate()`. 3344 3345 Developer Note: 3346 The Fortran interface is not autogenerated as the 3347 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3348 3349 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3350 @*/ 3351 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3352 { 3353 MatFactorInfo tinfo; 3354 3355 PetscFunctionBegin; 3356 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3358 PetscValidType(fact, 1); 3359 PetscValidType(mat, 2); 3360 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3361 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, 3362 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3363 3364 MatCheckPreallocated(mat, 2); 3365 if (!info) { 3366 PetscCall(MatFactorInfoInitialize(&tinfo)); 3367 info = &tinfo; 3368 } 3369 3370 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3371 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3372 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3373 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3374 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3375 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3376 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3377 PetscFunctionReturn(PETSC_SUCCESS); 3378 } 3379 3380 /*@ 3381 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3382 symmetric matrix. 3383 3384 Collective 3385 3386 Input Parameters: 3387 + mat - the matrix 3388 . perm - row and column permutations 3389 - info - expected fill as ratio of original fill 3390 3391 Level: developer 3392 3393 Notes: 3394 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3395 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3396 3397 Most users should employ the `KSP` interface for linear solvers 3398 instead of working directly with matrix algebra routines such as this. 3399 See, e.g., `KSPCreate()`. 3400 3401 Developer Note: 3402 The Fortran interface is not autogenerated as the 3403 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3404 3405 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3406 `MatGetOrdering()` 3407 @*/ 3408 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3409 { 3410 MatFactorInfo tinfo; 3411 3412 PetscFunctionBegin; 3413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3414 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3415 if (info) PetscAssertPointer(info, 3); 3416 PetscValidType(mat, 1); 3417 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3418 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3419 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3420 MatCheckPreallocated(mat, 1); 3421 if (!info) { 3422 PetscCall(MatFactorInfoInitialize(&tinfo)); 3423 info = &tinfo; 3424 } 3425 3426 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3427 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3428 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3429 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3430 PetscFunctionReturn(PETSC_SUCCESS); 3431 } 3432 3433 /*@ 3434 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3435 of a symmetric matrix. 3436 3437 Collective 3438 3439 Input Parameters: 3440 + fact - the factor matrix obtained with `MatGetFactor()` 3441 . mat - the matrix 3442 . perm - row and column permutations 3443 - info - options for factorization, includes 3444 .vb 3445 fill - expected fill as ratio of original fill. 3446 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3447 Run with the option -info to determine an optimal value to use 3448 .ve 3449 3450 Level: developer 3451 3452 Notes: 3453 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3454 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3455 3456 Most users should employ the `KSP` interface for linear solvers 3457 instead of working directly with matrix algebra routines such as this. 3458 See, e.g., `KSPCreate()`. 3459 3460 Developer Note: 3461 The Fortran interface is not autogenerated as the 3462 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3463 3464 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3465 `MatGetOrdering()` 3466 @*/ 3467 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3468 { 3469 MatFactorInfo tinfo; 3470 3471 PetscFunctionBegin; 3472 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3474 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3475 if (info) PetscAssertPointer(info, 4); 3476 PetscValidType(fact, 1); 3477 PetscValidType(mat, 2); 3478 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3479 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3480 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3481 MatCheckPreallocated(mat, 2); 3482 if (!info) { 3483 PetscCall(MatFactorInfoInitialize(&tinfo)); 3484 info = &tinfo; 3485 } 3486 3487 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3488 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3489 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3490 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3491 PetscFunctionReturn(PETSC_SUCCESS); 3492 } 3493 3494 /*@ 3495 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3496 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3497 `MatCholeskyFactorSymbolic()`. 3498 3499 Collective 3500 3501 Input Parameters: 3502 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3503 . mat - the initial matrix that is to be factored 3504 - info - options for factorization 3505 3506 Level: developer 3507 3508 Note: 3509 Most users should employ the `KSP` interface for linear solvers 3510 instead of working directly with matrix algebra routines such as this. 3511 See, e.g., `KSPCreate()`. 3512 3513 Developer Note: 3514 The Fortran interface is not autogenerated as the 3515 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3516 3517 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3518 @*/ 3519 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3520 { 3521 MatFactorInfo tinfo; 3522 3523 PetscFunctionBegin; 3524 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3525 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3526 PetscValidType(fact, 1); 3527 PetscValidType(mat, 2); 3528 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3529 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, 3530 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3531 MatCheckPreallocated(mat, 2); 3532 if (!info) { 3533 PetscCall(MatFactorInfoInitialize(&tinfo)); 3534 info = &tinfo; 3535 } 3536 3537 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3538 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3539 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3540 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3541 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3542 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3543 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3544 PetscFunctionReturn(PETSC_SUCCESS); 3545 } 3546 3547 /*@ 3548 MatQRFactor - Performs in-place QR factorization of matrix. 3549 3550 Collective 3551 3552 Input Parameters: 3553 + mat - the matrix 3554 . col - column permutation 3555 - info - options for factorization, includes 3556 .vb 3557 fill - expected fill as ratio of original fill. 3558 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3559 Run with the option -info to determine an optimal value to use 3560 .ve 3561 3562 Level: developer 3563 3564 Notes: 3565 Most users should employ the `KSP` interface for linear solvers 3566 instead of working directly with matrix algebra routines such as this. 3567 See, e.g., `KSPCreate()`. 3568 3569 This changes the state of the matrix to a factored matrix; it cannot be used 3570 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3571 3572 Developer Note: 3573 The Fortran interface is not autogenerated as the 3574 interface definition cannot be generated correctly [due to MatFactorInfo] 3575 3576 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3577 `MatSetUnfactored()` 3578 @*/ 3579 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3580 { 3581 PetscFunctionBegin; 3582 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3583 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3584 if (info) PetscAssertPointer(info, 3); 3585 PetscValidType(mat, 1); 3586 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3587 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3588 MatCheckPreallocated(mat, 1); 3589 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3590 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3591 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3592 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3593 PetscFunctionReturn(PETSC_SUCCESS); 3594 } 3595 3596 /*@ 3597 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3598 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3599 3600 Collective 3601 3602 Input Parameters: 3603 + fact - the factor matrix obtained with `MatGetFactor()` 3604 . mat - the matrix 3605 . col - column permutation 3606 - info - options for factorization, includes 3607 .vb 3608 fill - expected fill as ratio of original fill. 3609 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3610 Run with the option -info to determine an optimal value to use 3611 .ve 3612 3613 Level: developer 3614 3615 Note: 3616 Most users should employ the `KSP` interface for linear solvers 3617 instead of working directly with matrix algebra routines such as this. 3618 See, e.g., `KSPCreate()`. 3619 3620 Developer Note: 3621 The Fortran interface is not autogenerated as the 3622 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3623 3624 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3625 @*/ 3626 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3627 { 3628 MatFactorInfo tinfo; 3629 3630 PetscFunctionBegin; 3631 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3632 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3633 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3634 if (info) PetscAssertPointer(info, 4); 3635 PetscValidType(fact, 1); 3636 PetscValidType(mat, 2); 3637 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3638 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3639 MatCheckPreallocated(mat, 2); 3640 if (!info) { 3641 PetscCall(MatFactorInfoInitialize(&tinfo)); 3642 info = &tinfo; 3643 } 3644 3645 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3646 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3647 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3648 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3649 PetscFunctionReturn(PETSC_SUCCESS); 3650 } 3651 3652 /*@ 3653 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3654 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3655 3656 Collective 3657 3658 Input Parameters: 3659 + fact - the factor matrix obtained with `MatGetFactor()` 3660 . mat - the matrix 3661 - info - options for factorization 3662 3663 Level: developer 3664 3665 Notes: 3666 See `MatQRFactor()` for in-place factorization. 3667 3668 Most users should employ the `KSP` interface for linear solvers 3669 instead of working directly with matrix algebra routines such as this. 3670 See, e.g., `KSPCreate()`. 3671 3672 Developer Note: 3673 The Fortran interface is not autogenerated as the 3674 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3675 3676 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3677 @*/ 3678 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3679 { 3680 MatFactorInfo tinfo; 3681 3682 PetscFunctionBegin; 3683 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3684 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3685 PetscValidType(fact, 1); 3686 PetscValidType(mat, 2); 3687 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3688 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, 3689 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3690 3691 MatCheckPreallocated(mat, 2); 3692 if (!info) { 3693 PetscCall(MatFactorInfoInitialize(&tinfo)); 3694 info = &tinfo; 3695 } 3696 3697 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3698 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3699 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3700 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3701 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3702 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3703 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3704 PetscFunctionReturn(PETSC_SUCCESS); 3705 } 3706 3707 /*@ 3708 MatSolve - Solves $A x = b$, given a factored matrix. 3709 3710 Neighbor-wise Collective 3711 3712 Input Parameters: 3713 + mat - the factored matrix 3714 - b - the right-hand-side vector 3715 3716 Output Parameter: 3717 . x - the result vector 3718 3719 Level: developer 3720 3721 Notes: 3722 The vectors `b` and `x` cannot be the same. I.e., one cannot 3723 call `MatSolve`(A,x,x). 3724 3725 Most users should employ the `KSP` interface for linear solvers 3726 instead of working directly with matrix algebra routines such as this. 3727 See, e.g., `KSPCreate()`. 3728 3729 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3730 @*/ 3731 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3732 { 3733 PetscFunctionBegin; 3734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3735 PetscValidType(mat, 1); 3736 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3737 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3738 PetscCheckSameComm(mat, 1, b, 2); 3739 PetscCheckSameComm(mat, 1, x, 3); 3740 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3741 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); 3742 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); 3743 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); 3744 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3745 MatCheckPreallocated(mat, 1); 3746 3747 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3748 PetscCall(VecFlag(x, mat->factorerrortype)); 3749 if (mat->factorerrortype) { 3750 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3751 } else PetscUseTypeMethod(mat, solve, b, x); 3752 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3753 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3754 PetscFunctionReturn(PETSC_SUCCESS); 3755 } 3756 3757 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3758 { 3759 Vec b, x; 3760 PetscInt N, i; 3761 PetscErrorCode (*f)(Mat, Vec, Vec); 3762 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3763 3764 PetscFunctionBegin; 3765 if (A->factorerrortype) { 3766 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3767 PetscCall(MatSetInf(X)); 3768 PetscFunctionReturn(PETSC_SUCCESS); 3769 } 3770 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3771 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3772 PetscCall(MatBoundToCPU(A, &Abound)); 3773 if (!Abound) { 3774 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3775 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3776 } 3777 #if PetscDefined(HAVE_CUDA) 3778 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3779 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3780 #elif PetscDefined(HAVE_HIP) 3781 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3782 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3783 #endif 3784 PetscCall(MatGetSize(B, NULL, &N)); 3785 for (i = 0; i < N; i++) { 3786 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3787 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3788 PetscCall((*f)(A, b, x)); 3789 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3790 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3791 } 3792 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3793 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3794 PetscFunctionReturn(PETSC_SUCCESS); 3795 } 3796 3797 /*@ 3798 MatMatSolve - Solves $A X = B$, given a factored matrix. 3799 3800 Neighbor-wise Collective 3801 3802 Input Parameters: 3803 + A - the factored matrix 3804 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3805 3806 Output Parameter: 3807 . X - the result matrix (dense matrix) 3808 3809 Level: developer 3810 3811 Note: 3812 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3813 otherwise, `B` and `X` cannot be the same. 3814 3815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3816 @*/ 3817 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3818 { 3819 PetscFunctionBegin; 3820 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3821 PetscValidType(A, 1); 3822 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3823 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3824 PetscCheckSameComm(A, 1, B, 2); 3825 PetscCheckSameComm(A, 1, X, 3); 3826 PetscCheck(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); 3827 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); 3828 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"); 3829 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3830 MatCheckPreallocated(A, 1); 3831 3832 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3833 if (!A->ops->matsolve) { 3834 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3835 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3836 } else PetscUseTypeMethod(A, matsolve, B, X); 3837 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3838 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3839 PetscFunctionReturn(PETSC_SUCCESS); 3840 } 3841 3842 /*@ 3843 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3844 3845 Neighbor-wise Collective 3846 3847 Input Parameters: 3848 + A - the factored matrix 3849 - B - the right-hand-side matrix (`MATDENSE` matrix) 3850 3851 Output Parameter: 3852 . X - the result matrix (dense matrix) 3853 3854 Level: developer 3855 3856 Note: 3857 The matrices `B` and `X` cannot be the same. I.e., one cannot 3858 call `MatMatSolveTranspose`(A,X,X). 3859 3860 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3861 @*/ 3862 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3863 { 3864 PetscFunctionBegin; 3865 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3866 PetscValidType(A, 1); 3867 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3868 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3869 PetscCheckSameComm(A, 1, B, 2); 3870 PetscCheckSameComm(A, 1, X, 3); 3871 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3872 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); 3873 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); 3874 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); 3875 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"); 3876 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3877 MatCheckPreallocated(A, 1); 3878 3879 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3880 if (!A->ops->matsolvetranspose) { 3881 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3882 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3883 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3884 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3885 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3886 PetscFunctionReturn(PETSC_SUCCESS); 3887 } 3888 3889 /*@ 3890 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3891 3892 Neighbor-wise Collective 3893 3894 Input Parameters: 3895 + A - the factored matrix 3896 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3897 3898 Output Parameter: 3899 . X - the result matrix (dense matrix) 3900 3901 Level: developer 3902 3903 Note: 3904 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 3905 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3906 3907 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3908 @*/ 3909 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3910 { 3911 PetscFunctionBegin; 3912 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3913 PetscValidType(A, 1); 3914 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3915 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3916 PetscCheckSameComm(A, 1, Bt, 2); 3917 PetscCheckSameComm(A, 1, X, 3); 3918 3919 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3920 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); 3921 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); 3922 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"); 3923 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3924 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3925 MatCheckPreallocated(A, 1); 3926 3927 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3928 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3929 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3930 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3931 PetscFunctionReturn(PETSC_SUCCESS); 3932 } 3933 3934 /*@ 3935 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3936 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3937 3938 Neighbor-wise Collective 3939 3940 Input Parameters: 3941 + mat - the factored matrix 3942 - b - the right-hand-side vector 3943 3944 Output Parameter: 3945 . x - the result vector 3946 3947 Level: developer 3948 3949 Notes: 3950 `MatSolve()` should be used for most applications, as it performs 3951 a forward solve followed by a backward solve. 3952 3953 The vectors `b` and `x` cannot be the same, i.e., one cannot 3954 call `MatForwardSolve`(A,x,x). 3955 3956 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3957 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3958 `MatForwardSolve()` solves $U^T*D y = b$, and 3959 `MatBackwardSolve()` solves $U x = y$. 3960 Thus they do not provide a symmetric preconditioner. 3961 3962 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3963 @*/ 3964 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3965 { 3966 PetscFunctionBegin; 3967 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3968 PetscValidType(mat, 1); 3969 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3970 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3971 PetscCheckSameComm(mat, 1, b, 2); 3972 PetscCheckSameComm(mat, 1, x, 3); 3973 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3974 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); 3975 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); 3976 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); 3977 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3978 MatCheckPreallocated(mat, 1); 3979 3980 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3981 PetscUseTypeMethod(mat, forwardsolve, b, x); 3982 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3983 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3984 PetscFunctionReturn(PETSC_SUCCESS); 3985 } 3986 3987 /*@ 3988 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3989 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3990 3991 Neighbor-wise Collective 3992 3993 Input Parameters: 3994 + mat - the factored matrix 3995 - b - the right-hand-side vector 3996 3997 Output Parameter: 3998 . x - the result vector 3999 4000 Level: developer 4001 4002 Notes: 4003 `MatSolve()` should be used for most applications, as it performs 4004 a forward solve followed by a backward solve. 4005 4006 The vectors `b` and `x` cannot be the same. I.e., one cannot 4007 call `MatBackwardSolve`(A,x,x). 4008 4009 For matrix in `MATSEQBAIJ` format with block size larger than 1, 4010 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 4011 `MatForwardSolve()` solves $U^T*D y = b$, and 4012 `MatBackwardSolve()` solves $U x = y$. 4013 Thus they do not provide a symmetric preconditioner. 4014 4015 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 4016 @*/ 4017 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 4018 { 4019 PetscFunctionBegin; 4020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4021 PetscValidType(mat, 1); 4022 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4023 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4024 PetscCheckSameComm(mat, 1, b, 2); 4025 PetscCheckSameComm(mat, 1, x, 3); 4026 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4027 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); 4028 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); 4029 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); 4030 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4031 MatCheckPreallocated(mat, 1); 4032 4033 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 4034 PetscUseTypeMethod(mat, backwardsolve, b, x); 4035 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 4036 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4037 PetscFunctionReturn(PETSC_SUCCESS); 4038 } 4039 4040 /*@ 4041 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4042 4043 Neighbor-wise Collective 4044 4045 Input Parameters: 4046 + mat - the factored matrix 4047 . b - the right-hand-side vector 4048 - y - the vector to be added to 4049 4050 Output Parameter: 4051 . x - the result vector 4052 4053 Level: developer 4054 4055 Note: 4056 The vectors `b` and `x` cannot be the same. I.e., one cannot 4057 call `MatSolveAdd`(A,x,y,x). 4058 4059 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4060 @*/ 4061 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4062 { 4063 PetscScalar one = 1.0; 4064 Vec tmp; 4065 4066 PetscFunctionBegin; 4067 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4068 PetscValidType(mat, 1); 4069 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4070 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4071 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4072 PetscCheckSameComm(mat, 1, b, 2); 4073 PetscCheckSameComm(mat, 1, y, 3); 4074 PetscCheckSameComm(mat, 1, x, 4); 4075 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4076 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); 4077 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); 4078 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); 4079 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); 4080 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); 4081 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4082 MatCheckPreallocated(mat, 1); 4083 4084 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4085 PetscCall(VecFlag(x, mat->factorerrortype)); 4086 if (mat->factorerrortype) { 4087 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4088 } else if (mat->ops->solveadd) { 4089 PetscUseTypeMethod(mat, solveadd, b, y, x); 4090 } else { 4091 /* do the solve then the add manually */ 4092 if (x != y) { 4093 PetscCall(MatSolve(mat, b, x)); 4094 PetscCall(VecAXPY(x, one, y)); 4095 } else { 4096 PetscCall(VecDuplicate(x, &tmp)); 4097 PetscCall(VecCopy(x, tmp)); 4098 PetscCall(MatSolve(mat, b, x)); 4099 PetscCall(VecAXPY(x, one, tmp)); 4100 PetscCall(VecDestroy(&tmp)); 4101 } 4102 } 4103 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4104 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4105 PetscFunctionReturn(PETSC_SUCCESS); 4106 } 4107 4108 /*@ 4109 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4110 4111 Neighbor-wise Collective 4112 4113 Input Parameters: 4114 + mat - the factored matrix 4115 - b - the right-hand-side vector 4116 4117 Output Parameter: 4118 . x - the result vector 4119 4120 Level: developer 4121 4122 Notes: 4123 The vectors `b` and `x` cannot be the same. I.e., one cannot 4124 call `MatSolveTranspose`(A,x,x). 4125 4126 Most users should employ the `KSP` interface for linear solvers 4127 instead of working directly with matrix algebra routines such as this. 4128 See, e.g., `KSPCreate()`. 4129 4130 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4131 @*/ 4132 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4133 { 4134 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4135 4136 PetscFunctionBegin; 4137 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4138 PetscValidType(mat, 1); 4139 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4140 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4141 PetscCheckSameComm(mat, 1, b, 2); 4142 PetscCheckSameComm(mat, 1, x, 3); 4143 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4144 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); 4145 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); 4146 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4147 MatCheckPreallocated(mat, 1); 4148 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4149 PetscCall(VecFlag(x, mat->factorerrortype)); 4150 if (mat->factorerrortype) { 4151 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4152 } else { 4153 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4154 PetscCall((*f)(mat, b, x)); 4155 } 4156 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4157 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4158 PetscFunctionReturn(PETSC_SUCCESS); 4159 } 4160 4161 /*@ 4162 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4163 factored matrix. 4164 4165 Neighbor-wise Collective 4166 4167 Input Parameters: 4168 + mat - the factored matrix 4169 . b - the right-hand-side vector 4170 - y - the vector to be added to 4171 4172 Output Parameter: 4173 . x - the result vector 4174 4175 Level: developer 4176 4177 Note: 4178 The vectors `b` and `x` cannot be the same. I.e., one cannot 4179 call `MatSolveTransposeAdd`(A,x,y,x). 4180 4181 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4182 @*/ 4183 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4184 { 4185 PetscScalar one = 1.0; 4186 Vec tmp; 4187 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4188 4189 PetscFunctionBegin; 4190 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4191 PetscValidType(mat, 1); 4192 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4193 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4194 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4195 PetscCheckSameComm(mat, 1, b, 2); 4196 PetscCheckSameComm(mat, 1, y, 3); 4197 PetscCheckSameComm(mat, 1, x, 4); 4198 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4199 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); 4200 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); 4201 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); 4202 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); 4203 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4204 MatCheckPreallocated(mat, 1); 4205 4206 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4207 PetscCall(VecFlag(x, mat->factorerrortype)); 4208 if (mat->factorerrortype) { 4209 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4210 } else if (f) { 4211 PetscCall((*f)(mat, b, y, x)); 4212 } else { 4213 /* do the solve then the add manually */ 4214 if (x != y) { 4215 PetscCall(MatSolveTranspose(mat, b, x)); 4216 PetscCall(VecAXPY(x, one, y)); 4217 } else { 4218 PetscCall(VecDuplicate(x, &tmp)); 4219 PetscCall(VecCopy(x, tmp)); 4220 PetscCall(MatSolveTranspose(mat, b, x)); 4221 PetscCall(VecAXPY(x, one, tmp)); 4222 PetscCall(VecDestroy(&tmp)); 4223 } 4224 } 4225 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4226 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4227 PetscFunctionReturn(PETSC_SUCCESS); 4228 } 4229 4230 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4231 /*@ 4232 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4233 4234 Neighbor-wise Collective 4235 4236 Input Parameters: 4237 + mat - the matrix 4238 . b - the right-hand side 4239 . omega - the relaxation factor 4240 . flag - flag indicating the type of SOR (see below) 4241 . shift - diagonal shift 4242 . its - the number of iterations 4243 - lits - the number of local iterations 4244 4245 Output Parameter: 4246 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4247 4248 SOR Flags: 4249 + `SOR_FORWARD_SWEEP` - forward SOR 4250 . `SOR_BACKWARD_SWEEP` - backward SOR 4251 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4252 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4253 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4254 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4255 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4256 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4257 upper/lower triangular part of matrix to 4258 vector (with omega) 4259 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4260 4261 Level: developer 4262 4263 Notes: 4264 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4265 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4266 on each processor. 4267 4268 Application programmers will not generally use `MatSOR()` directly, 4269 but instead will employ the `KSP`/`PC` interface. 4270 4271 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4272 4273 Most users should employ the `KSP` interface for linear solvers 4274 instead of working directly with matrix algebra routines such as this. 4275 See, e.g., `KSPCreate()`. 4276 4277 Vectors `x` and `b` CANNOT be the same 4278 4279 The flags are implemented as bitwise inclusive or operations. 4280 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4281 to specify a zero initial guess for SSOR. 4282 4283 Developer Note: 4284 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4285 4286 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4287 @*/ 4288 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4289 { 4290 PetscFunctionBegin; 4291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4292 PetscValidType(mat, 1); 4293 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4294 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4295 PetscCheckSameComm(mat, 1, b, 2); 4296 PetscCheckSameComm(mat, 1, x, 8); 4297 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4298 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4299 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); 4300 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); 4301 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); 4302 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4303 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4304 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4305 4306 MatCheckPreallocated(mat, 1); 4307 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4308 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4309 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4310 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4311 PetscFunctionReturn(PETSC_SUCCESS); 4312 } 4313 4314 /* 4315 Default matrix copy routine. 4316 */ 4317 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4318 { 4319 PetscInt i, rstart = 0, rend = 0, nz; 4320 const PetscInt *cwork; 4321 const PetscScalar *vwork; 4322 4323 PetscFunctionBegin; 4324 if (B->assembled) PetscCall(MatZeroEntries(B)); 4325 if (str == SAME_NONZERO_PATTERN) { 4326 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4327 for (i = rstart; i < rend; i++) { 4328 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4329 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4330 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4331 } 4332 } else { 4333 PetscCall(MatAYPX(B, 0.0, A, str)); 4334 } 4335 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4336 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4337 PetscFunctionReturn(PETSC_SUCCESS); 4338 } 4339 4340 /*@ 4341 MatCopy - Copies a matrix to another matrix. 4342 4343 Collective 4344 4345 Input Parameters: 4346 + A - the matrix 4347 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4348 4349 Output Parameter: 4350 . B - where the copy is put 4351 4352 Level: intermediate 4353 4354 Notes: 4355 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4356 4357 `MatCopy()` copies the matrix entries of a matrix to another existing 4358 matrix (after first zeroing the second matrix). A related routine is 4359 `MatConvert()`, which first creates a new matrix and then copies the data. 4360 4361 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4362 @*/ 4363 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4364 { 4365 PetscInt i; 4366 4367 PetscFunctionBegin; 4368 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4369 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4370 PetscValidType(A, 1); 4371 PetscValidType(B, 2); 4372 PetscCheckSameComm(A, 1, B, 2); 4373 MatCheckPreallocated(B, 2); 4374 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4375 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4376 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, 4377 A->cmap->N, B->cmap->N); 4378 MatCheckPreallocated(A, 1); 4379 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4380 4381 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4382 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4383 else PetscCall(MatCopy_Basic(A, B, str)); 4384 4385 B->stencil.dim = A->stencil.dim; 4386 B->stencil.noc = A->stencil.noc; 4387 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4388 B->stencil.dims[i] = A->stencil.dims[i]; 4389 B->stencil.starts[i] = A->stencil.starts[i]; 4390 } 4391 4392 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4393 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4394 PetscFunctionReturn(PETSC_SUCCESS); 4395 } 4396 4397 /*@ 4398 MatConvert - Converts a matrix to another matrix, either of the same 4399 or different type. 4400 4401 Collective 4402 4403 Input Parameters: 4404 + mat - the matrix 4405 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4406 same type as the original matrix. 4407 - reuse - denotes if the destination matrix is to be created or reused. 4408 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 4409 `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). 4410 4411 Output Parameter: 4412 . M - pointer to place new matrix 4413 4414 Level: intermediate 4415 4416 Notes: 4417 `MatConvert()` first creates a new matrix and then copies the data from 4418 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4419 entries of one matrix to another already existing matrix context. 4420 4421 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4422 the MPI communicator of the generated matrix is always the same as the communicator 4423 of the input matrix. 4424 4425 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4426 @*/ 4427 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4428 { 4429 PetscBool sametype, issame, flg; 4430 PetscBool3 issymmetric, ishermitian; 4431 char convname[256], mtype[256]; 4432 Mat B; 4433 4434 PetscFunctionBegin; 4435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4436 PetscValidType(mat, 1); 4437 PetscAssertPointer(M, 4); 4438 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4439 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4440 MatCheckPreallocated(mat, 1); 4441 4442 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4443 if (flg) newtype = mtype; 4444 4445 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4446 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4447 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4448 if (reuse == MAT_REUSE_MATRIX) { 4449 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4450 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4451 } 4452 4453 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4454 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4455 PetscFunctionReturn(PETSC_SUCCESS); 4456 } 4457 4458 /* Cache Mat options because some converters use MatHeaderReplace */ 4459 issymmetric = mat->symmetric; 4460 ishermitian = mat->hermitian; 4461 4462 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4463 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4464 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4465 } else { 4466 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4467 const char *prefix[3] = {"seq", "mpi", ""}; 4468 PetscInt i; 4469 /* 4470 Order of precedence: 4471 0) See if newtype is a superclass of the current matrix. 4472 1) See if a specialized converter is known to the current matrix. 4473 2) See if a specialized converter is known to the desired matrix class. 4474 3) See if a good general converter is registered for the desired class 4475 (as of 6/27/03 only MATMPIADJ falls into this category). 4476 4) See if a good general converter is known for the current matrix. 4477 5) Use a really basic converter. 4478 */ 4479 4480 /* 0) See if newtype is a superclass of the current matrix. 4481 i.e mat is mpiaij and newtype is aij */ 4482 for (i = 0; i < 2; i++) { 4483 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4484 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4485 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4486 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4487 if (flg) { 4488 if (reuse == MAT_INPLACE_MATRIX) { 4489 PetscCall(PetscInfo(mat, "Early return\n")); 4490 PetscFunctionReturn(PETSC_SUCCESS); 4491 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4492 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4493 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4494 PetscFunctionReturn(PETSC_SUCCESS); 4495 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4496 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4497 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4498 PetscFunctionReturn(PETSC_SUCCESS); 4499 } 4500 } 4501 } 4502 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4503 for (i = 0; i < 3; i++) { 4504 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4505 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4506 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4507 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4508 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4509 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4510 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4511 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4512 if (conv) goto foundconv; 4513 } 4514 4515 /* 2) See if a specialized converter is known to the desired matrix class. */ 4516 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4517 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4518 PetscCall(MatSetType(B, newtype)); 4519 for (i = 0; i < 3; i++) { 4520 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4521 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4522 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4523 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4524 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4525 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4526 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4527 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4528 if (conv) { 4529 PetscCall(MatDestroy(&B)); 4530 goto foundconv; 4531 } 4532 } 4533 4534 /* 3) See if a good general converter is registered for the desired class */ 4535 conv = B->ops->convertfrom; 4536 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4537 PetscCall(MatDestroy(&B)); 4538 if (conv) goto foundconv; 4539 4540 /* 4) See if a good general converter is known for the current matrix */ 4541 if (mat->ops->convert) conv = mat->ops->convert; 4542 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4543 if (conv) goto foundconv; 4544 4545 /* 5) Use a really basic converter. */ 4546 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4547 conv = MatConvert_Basic; 4548 4549 foundconv: 4550 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4551 PetscCall((*conv)(mat, newtype, reuse, M)); 4552 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4553 /* the block sizes must be same if the mappings are copied over */ 4554 (*M)->rmap->bs = mat->rmap->bs; 4555 (*M)->cmap->bs = mat->cmap->bs; 4556 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4557 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4558 (*M)->rmap->mapping = mat->rmap->mapping; 4559 (*M)->cmap->mapping = mat->cmap->mapping; 4560 } 4561 (*M)->stencil.dim = mat->stencil.dim; 4562 (*M)->stencil.noc = mat->stencil.noc; 4563 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4564 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4565 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4566 } 4567 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4568 } 4569 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4570 4571 /* Copy Mat options */ 4572 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4573 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4574 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4575 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4576 PetscFunctionReturn(PETSC_SUCCESS); 4577 } 4578 4579 /*@ 4580 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4581 4582 Not Collective 4583 4584 Input Parameter: 4585 . mat - the matrix, must be a factored matrix 4586 4587 Output Parameter: 4588 . type - the string name of the package (do not free this string) 4589 4590 Level: intermediate 4591 4592 Fortran Note: 4593 Pass in an empty string that is long enough and the package name will be copied into it. 4594 4595 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4596 @*/ 4597 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4598 { 4599 PetscErrorCode (*conv)(Mat, MatSolverType *); 4600 4601 PetscFunctionBegin; 4602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4603 PetscValidType(mat, 1); 4604 PetscAssertPointer(type, 2); 4605 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4606 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4607 if (conv) PetscCall((*conv)(mat, type)); 4608 else *type = MATSOLVERPETSC; 4609 PetscFunctionReturn(PETSC_SUCCESS); 4610 } 4611 4612 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4613 struct _MatSolverTypeForSpecifcType { 4614 MatType mtype; 4615 /* no entry for MAT_FACTOR_NONE */ 4616 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4617 MatSolverTypeForSpecifcType next; 4618 }; 4619 4620 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4621 struct _MatSolverTypeHolder { 4622 char *name; 4623 MatSolverTypeForSpecifcType handlers; 4624 MatSolverTypeHolder next; 4625 }; 4626 4627 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4628 4629 /*@C 4630 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4631 4632 Logically Collective, No Fortran Support 4633 4634 Input Parameters: 4635 + package - name of the package, for example petsc or superlu 4636 . mtype - the matrix type that works with this package 4637 . ftype - the type of factorization supported by the package 4638 - createfactor - routine that will create the factored matrix ready to be used 4639 4640 Level: developer 4641 4642 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4643 `MatGetFactor()` 4644 @*/ 4645 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4646 { 4647 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4648 PetscBool flg; 4649 MatSolverTypeForSpecifcType inext, iprev = NULL; 4650 4651 PetscFunctionBegin; 4652 PetscCall(MatInitializePackage()); 4653 if (!next) { 4654 PetscCall(PetscNew(&MatSolverTypeHolders)); 4655 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4656 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4657 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4658 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4659 PetscFunctionReturn(PETSC_SUCCESS); 4660 } 4661 while (next) { 4662 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4663 if (flg) { 4664 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4665 inext = next->handlers; 4666 while (inext) { 4667 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4668 if (flg) { 4669 inext->createfactor[(int)ftype - 1] = createfactor; 4670 PetscFunctionReturn(PETSC_SUCCESS); 4671 } 4672 iprev = inext; 4673 inext = inext->next; 4674 } 4675 PetscCall(PetscNew(&iprev->next)); 4676 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4677 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4678 PetscFunctionReturn(PETSC_SUCCESS); 4679 } 4680 prev = next; 4681 next = next->next; 4682 } 4683 PetscCall(PetscNew(&prev->next)); 4684 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4685 PetscCall(PetscNew(&prev->next->handlers)); 4686 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4687 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4688 PetscFunctionReturn(PETSC_SUCCESS); 4689 } 4690 4691 /*@C 4692 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4693 4694 Input Parameters: 4695 + 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 4696 . ftype - the type of factorization supported by the type 4697 - mtype - the matrix type that works with this type 4698 4699 Output Parameters: 4700 + foundtype - `PETSC_TRUE` if the type was registered 4701 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4702 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4703 4704 Calling sequence of `createfactor`: 4705 + A - the matrix providing the factor matrix 4706 . ftype - the `MatFactorType` of the factor requested 4707 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4708 4709 Level: developer 4710 4711 Note: 4712 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4713 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4714 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4715 4716 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4717 `MatInitializePackage()` 4718 @*/ 4719 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4720 { 4721 MatSolverTypeHolder next = MatSolverTypeHolders; 4722 PetscBool flg; 4723 MatSolverTypeForSpecifcType inext; 4724 4725 PetscFunctionBegin; 4726 if (foundtype) *foundtype = PETSC_FALSE; 4727 if (foundmtype) *foundmtype = PETSC_FALSE; 4728 if (createfactor) *createfactor = NULL; 4729 4730 if (type) { 4731 while (next) { 4732 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4733 if (flg) { 4734 if (foundtype) *foundtype = PETSC_TRUE; 4735 inext = next->handlers; 4736 while (inext) { 4737 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4738 if (flg) { 4739 if (foundmtype) *foundmtype = PETSC_TRUE; 4740 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4741 PetscFunctionReturn(PETSC_SUCCESS); 4742 } 4743 inext = inext->next; 4744 } 4745 } 4746 next = next->next; 4747 } 4748 } else { 4749 while (next) { 4750 inext = next->handlers; 4751 while (inext) { 4752 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4753 if (flg && inext->createfactor[(int)ftype - 1]) { 4754 if (foundtype) *foundtype = PETSC_TRUE; 4755 if (foundmtype) *foundmtype = PETSC_TRUE; 4756 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4757 PetscFunctionReturn(PETSC_SUCCESS); 4758 } 4759 inext = inext->next; 4760 } 4761 next = next->next; 4762 } 4763 /* try with base classes inext->mtype */ 4764 next = MatSolverTypeHolders; 4765 while (next) { 4766 inext = next->handlers; 4767 while (inext) { 4768 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4769 if (flg && inext->createfactor[(int)ftype - 1]) { 4770 if (foundtype) *foundtype = PETSC_TRUE; 4771 if (foundmtype) *foundmtype = PETSC_TRUE; 4772 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4773 PetscFunctionReturn(PETSC_SUCCESS); 4774 } 4775 inext = inext->next; 4776 } 4777 next = next->next; 4778 } 4779 } 4780 PetscFunctionReturn(PETSC_SUCCESS); 4781 } 4782 4783 PetscErrorCode MatSolverTypeDestroy(void) 4784 { 4785 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4786 MatSolverTypeForSpecifcType inext, iprev; 4787 4788 PetscFunctionBegin; 4789 while (next) { 4790 PetscCall(PetscFree(next->name)); 4791 inext = next->handlers; 4792 while (inext) { 4793 PetscCall(PetscFree(inext->mtype)); 4794 iprev = inext; 4795 inext = inext->next; 4796 PetscCall(PetscFree(iprev)); 4797 } 4798 prev = next; 4799 next = next->next; 4800 PetscCall(PetscFree(prev)); 4801 } 4802 MatSolverTypeHolders = NULL; 4803 PetscFunctionReturn(PETSC_SUCCESS); 4804 } 4805 4806 /*@ 4807 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4808 4809 Logically Collective 4810 4811 Input Parameter: 4812 . mat - the matrix 4813 4814 Output Parameter: 4815 . flg - `PETSC_TRUE` if uses the ordering 4816 4817 Level: developer 4818 4819 Note: 4820 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4821 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4822 4823 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4824 @*/ 4825 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4826 { 4827 PetscFunctionBegin; 4828 *flg = mat->canuseordering; 4829 PetscFunctionReturn(PETSC_SUCCESS); 4830 } 4831 4832 /*@ 4833 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4834 4835 Logically Collective 4836 4837 Input Parameters: 4838 + mat - the matrix obtained with `MatGetFactor()` 4839 - ftype - the factorization type to be used 4840 4841 Output Parameter: 4842 . otype - the preferred ordering type 4843 4844 Level: developer 4845 4846 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4847 @*/ 4848 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4849 { 4850 PetscFunctionBegin; 4851 *otype = mat->preferredordering[ftype]; 4852 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4853 PetscFunctionReturn(PETSC_SUCCESS); 4854 } 4855 4856 /*@ 4857 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4858 4859 Collective 4860 4861 Input Parameters: 4862 + mat - the matrix 4863 . 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 4864 the other criteria is returned 4865 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4866 4867 Output Parameter: 4868 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4869 4870 Options Database Keys: 4871 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4872 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4873 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4874 4875 Level: intermediate 4876 4877 Notes: 4878 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4879 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4880 4881 Users usually access the factorization solvers via `KSP` 4882 4883 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4884 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 4885 4886 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4887 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4888 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4889 4890 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4891 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4892 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4893 4894 Developer Note: 4895 This should actually be called `MatCreateFactor()` since it creates a new factor object 4896 4897 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4898 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4899 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4900 @*/ 4901 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4902 { 4903 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4904 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4905 4906 PetscFunctionBegin; 4907 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4908 PetscValidType(mat, 1); 4909 4910 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4911 MatCheckPreallocated(mat, 1); 4912 4913 PetscCall(MatIsShell(mat, &shell)); 4914 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4915 if (hasop) { 4916 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4917 PetscFunctionReturn(PETSC_SUCCESS); 4918 } 4919 4920 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4921 if (!foundtype) { 4922 if (type) { 4923 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], 4924 ((PetscObject)mat)->type_name, type); 4925 } else { 4926 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); 4927 } 4928 } 4929 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4930 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); 4931 4932 PetscCall((*conv)(mat, ftype, f)); 4933 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4934 PetscFunctionReturn(PETSC_SUCCESS); 4935 } 4936 4937 /*@ 4938 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4939 4940 Not Collective 4941 4942 Input Parameters: 4943 + mat - the matrix 4944 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4945 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4946 4947 Output Parameter: 4948 . flg - PETSC_TRUE if the factorization is available 4949 4950 Level: intermediate 4951 4952 Notes: 4953 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4954 such as pastix, superlu, mumps etc. 4955 4956 PETSc must have been ./configure to use the external solver, using the option --download-package 4957 4958 Developer Note: 4959 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4960 4961 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4962 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4963 @*/ 4964 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4965 { 4966 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4967 4968 PetscFunctionBegin; 4969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4970 PetscAssertPointer(flg, 4); 4971 4972 *flg = PETSC_FALSE; 4973 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4974 4975 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4976 MatCheckPreallocated(mat, 1); 4977 4978 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4979 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4980 PetscFunctionReturn(PETSC_SUCCESS); 4981 } 4982 4983 /*@ 4984 MatDuplicate - Duplicates a matrix including the non-zero structure. 4985 4986 Collective 4987 4988 Input Parameters: 4989 + mat - the matrix 4990 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4991 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4992 4993 Output Parameter: 4994 . M - pointer to place new matrix 4995 4996 Level: intermediate 4997 4998 Notes: 4999 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 5000 5001 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 5002 5003 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. 5004 5005 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 5006 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 5007 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 5008 5009 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 5010 @*/ 5011 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 5012 { 5013 Mat B; 5014 VecType vtype; 5015 PetscInt i; 5016 PetscObject dm, container_h, container_d; 5017 void (*viewf)(void); 5018 5019 PetscFunctionBegin; 5020 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5021 PetscValidType(mat, 1); 5022 PetscAssertPointer(M, 3); 5023 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 5024 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5025 MatCheckPreallocated(mat, 1); 5026 5027 *M = NULL; 5028 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 5029 PetscUseTypeMethod(mat, duplicate, op, M); 5030 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 5031 B = *M; 5032 5033 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 5034 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 5035 PetscCall(MatGetVecType(mat, &vtype)); 5036 PetscCall(MatSetVecType(B, vtype)); 5037 5038 B->stencil.dim = mat->stencil.dim; 5039 B->stencil.noc = mat->stencil.noc; 5040 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 5041 B->stencil.dims[i] = mat->stencil.dims[i]; 5042 B->stencil.starts[i] = mat->stencil.starts[i]; 5043 } 5044 5045 B->nooffproczerorows = mat->nooffproczerorows; 5046 B->nooffprocentries = mat->nooffprocentries; 5047 5048 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5049 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5050 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5051 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5052 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5053 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5054 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5055 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5056 PetscFunctionReturn(PETSC_SUCCESS); 5057 } 5058 5059 /*@ 5060 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5061 5062 Logically Collective 5063 5064 Input Parameter: 5065 . mat - the matrix 5066 5067 Output Parameter: 5068 . v - the diagonal of the matrix 5069 5070 Level: intermediate 5071 5072 Note: 5073 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5074 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5075 is larger than `ndiag`, the values of the remaining entries are unspecified. 5076 5077 Currently only correct in parallel for square matrices. 5078 5079 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5080 @*/ 5081 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5082 { 5083 PetscFunctionBegin; 5084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5085 PetscValidType(mat, 1); 5086 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5087 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5088 MatCheckPreallocated(mat, 1); 5089 if (PetscDefined(USE_DEBUG)) { 5090 PetscInt nv, row, col, ndiag; 5091 5092 PetscCall(VecGetLocalSize(v, &nv)); 5093 PetscCall(MatGetLocalSize(mat, &row, &col)); 5094 ndiag = PetscMin(row, col); 5095 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); 5096 } 5097 5098 PetscUseTypeMethod(mat, getdiagonal, v); 5099 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5100 PetscFunctionReturn(PETSC_SUCCESS); 5101 } 5102 5103 /*@ 5104 MatGetRowMin - Gets the minimum value (of the real part) of each 5105 row of the matrix 5106 5107 Logically Collective 5108 5109 Input Parameter: 5110 . mat - the matrix 5111 5112 Output Parameters: 5113 + v - the vector for storing the maximums 5114 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5115 5116 Level: intermediate 5117 5118 Note: 5119 The result of this call are the same as if one converted the matrix to dense format 5120 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5121 5122 This code is only implemented for a couple of matrix formats. 5123 5124 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5125 `MatGetRowMax()` 5126 @*/ 5127 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5128 { 5129 PetscFunctionBegin; 5130 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5131 PetscValidType(mat, 1); 5132 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5133 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5134 5135 if (!mat->cmap->N) { 5136 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5137 if (idx) { 5138 PetscInt i, m = mat->rmap->n; 5139 for (i = 0; i < m; i++) idx[i] = -1; 5140 } 5141 } else { 5142 MatCheckPreallocated(mat, 1); 5143 } 5144 PetscUseTypeMethod(mat, getrowmin, v, idx); 5145 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5146 PetscFunctionReturn(PETSC_SUCCESS); 5147 } 5148 5149 /*@ 5150 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5151 row of the matrix 5152 5153 Logically Collective 5154 5155 Input Parameter: 5156 . mat - the matrix 5157 5158 Output Parameters: 5159 + v - the vector for storing the minimums 5160 - idx - the indices of the column found for each row (or `NULL` if not needed) 5161 5162 Level: intermediate 5163 5164 Notes: 5165 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5166 row is 0 (the first column). 5167 5168 This code is only implemented for a couple of matrix formats. 5169 5170 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5171 @*/ 5172 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5173 { 5174 PetscFunctionBegin; 5175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5176 PetscValidType(mat, 1); 5177 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5178 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5179 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5180 5181 if (!mat->cmap->N) { 5182 PetscCall(VecSet(v, 0.0)); 5183 if (idx) { 5184 PetscInt i, m = mat->rmap->n; 5185 for (i = 0; i < m; i++) idx[i] = -1; 5186 } 5187 } else { 5188 MatCheckPreallocated(mat, 1); 5189 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5190 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5191 } 5192 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5193 PetscFunctionReturn(PETSC_SUCCESS); 5194 } 5195 5196 /*@ 5197 MatGetRowMax - Gets the maximum value (of the real part) of each 5198 row of the matrix 5199 5200 Logically Collective 5201 5202 Input Parameter: 5203 . mat - the matrix 5204 5205 Output Parameters: 5206 + v - the vector for storing the maximums 5207 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5208 5209 Level: intermediate 5210 5211 Notes: 5212 The result of this call are the same as if one converted the matrix to dense format 5213 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5214 5215 This code is only implemented for a couple of matrix formats. 5216 5217 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5218 @*/ 5219 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5220 { 5221 PetscFunctionBegin; 5222 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5223 PetscValidType(mat, 1); 5224 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5225 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5226 5227 if (!mat->cmap->N) { 5228 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5229 if (idx) { 5230 PetscInt i, m = mat->rmap->n; 5231 for (i = 0; i < m; i++) idx[i] = -1; 5232 } 5233 } else { 5234 MatCheckPreallocated(mat, 1); 5235 PetscUseTypeMethod(mat, getrowmax, v, idx); 5236 } 5237 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5238 PetscFunctionReturn(PETSC_SUCCESS); 5239 } 5240 5241 /*@ 5242 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5243 row of the matrix 5244 5245 Logically Collective 5246 5247 Input Parameter: 5248 . mat - the matrix 5249 5250 Output Parameters: 5251 + v - the vector for storing the maximums 5252 - idx - the indices of the column found for each row (or `NULL` if not needed) 5253 5254 Level: intermediate 5255 5256 Notes: 5257 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5258 row is 0 (the first column). 5259 5260 This code is only implemented for a couple of matrix formats. 5261 5262 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5263 @*/ 5264 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5265 { 5266 PetscFunctionBegin; 5267 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5268 PetscValidType(mat, 1); 5269 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5270 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5271 5272 if (!mat->cmap->N) { 5273 PetscCall(VecSet(v, 0.0)); 5274 if (idx) { 5275 PetscInt i, m = mat->rmap->n; 5276 for (i = 0; i < m; i++) idx[i] = -1; 5277 } 5278 } else { 5279 MatCheckPreallocated(mat, 1); 5280 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5281 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5282 } 5283 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5284 PetscFunctionReturn(PETSC_SUCCESS); 5285 } 5286 5287 /*@ 5288 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5289 5290 Logically Collective 5291 5292 Input Parameter: 5293 . mat - the matrix 5294 5295 Output Parameter: 5296 . v - the vector for storing the sum 5297 5298 Level: intermediate 5299 5300 This code is only implemented for a couple of matrix formats. 5301 5302 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5303 @*/ 5304 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5305 { 5306 PetscFunctionBegin; 5307 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5308 PetscValidType(mat, 1); 5309 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5310 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5311 5312 if (!mat->cmap->N) { 5313 PetscCall(VecSet(v, 0.0)); 5314 } else { 5315 MatCheckPreallocated(mat, 1); 5316 PetscUseTypeMethod(mat, getrowsumabs, v); 5317 } 5318 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5319 PetscFunctionReturn(PETSC_SUCCESS); 5320 } 5321 5322 /*@ 5323 MatGetRowSum - Gets the sum of each row of the matrix 5324 5325 Logically or Neighborhood Collective 5326 5327 Input Parameter: 5328 . mat - the matrix 5329 5330 Output Parameter: 5331 . v - the vector for storing the sum of rows 5332 5333 Level: intermediate 5334 5335 Note: 5336 This code is slow since it is not currently specialized for different formats 5337 5338 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5339 @*/ 5340 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5341 { 5342 Vec ones; 5343 5344 PetscFunctionBegin; 5345 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5346 PetscValidType(mat, 1); 5347 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5348 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5349 MatCheckPreallocated(mat, 1); 5350 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5351 PetscCall(VecSet(ones, 1.)); 5352 PetscCall(MatMult(mat, ones, v)); 5353 PetscCall(VecDestroy(&ones)); 5354 PetscFunctionReturn(PETSC_SUCCESS); 5355 } 5356 5357 /*@ 5358 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5359 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5360 5361 Collective 5362 5363 Input Parameter: 5364 . mat - the matrix to provide the transpose 5365 5366 Output Parameter: 5367 . 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 5368 5369 Level: advanced 5370 5371 Note: 5372 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 5373 routine allows bypassing that call. 5374 5375 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5376 @*/ 5377 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5378 { 5379 MatParentState *rb = NULL; 5380 5381 PetscFunctionBegin; 5382 PetscCall(PetscNew(&rb)); 5383 rb->id = ((PetscObject)mat)->id; 5384 rb->state = 0; 5385 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5386 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5387 PetscFunctionReturn(PETSC_SUCCESS); 5388 } 5389 5390 /*@ 5391 MatTranspose - Computes an in-place or out-of-place transpose of a matrix. 5392 5393 Collective 5394 5395 Input Parameters: 5396 + mat - the matrix to transpose 5397 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5398 5399 Output Parameter: 5400 . B - the transpose 5401 5402 Level: intermediate 5403 5404 Notes: 5405 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5406 5407 `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 5408 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5409 5410 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. 5411 5412 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed. 5413 5414 If mat is unchanged from the last call this function returns immediately without recomputing the result 5415 5416 If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()` 5417 5418 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5419 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5420 @*/ 5421 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5422 { 5423 PetscContainer rB = NULL; 5424 MatParentState *rb = NULL; 5425 5426 PetscFunctionBegin; 5427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5428 PetscValidType(mat, 1); 5429 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5430 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5431 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5432 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5433 MatCheckPreallocated(mat, 1); 5434 if (reuse == MAT_REUSE_MATRIX) { 5435 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5436 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5437 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5438 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5439 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5440 } 5441 5442 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5443 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5444 PetscUseTypeMethod(mat, transpose, reuse, B); 5445 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5446 } 5447 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5448 5449 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5450 if (reuse != MAT_INPLACE_MATRIX) { 5451 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5452 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5453 rb->state = ((PetscObject)mat)->state; 5454 rb->nonzerostate = mat->nonzerostate; 5455 } 5456 PetscFunctionReturn(PETSC_SUCCESS); 5457 } 5458 5459 /*@ 5460 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5461 5462 Collective 5463 5464 Input Parameter: 5465 . A - the matrix to transpose 5466 5467 Output Parameter: 5468 . 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 5469 numerical portion. 5470 5471 Level: intermediate 5472 5473 Note: 5474 This is not supported for many matrix types, use `MatTranspose()` in those cases 5475 5476 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5477 @*/ 5478 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5479 { 5480 PetscFunctionBegin; 5481 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5482 PetscValidType(A, 1); 5483 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5484 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5485 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5486 PetscUseTypeMethod(A, transposesymbolic, B); 5487 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5488 5489 PetscCall(MatTransposeSetPrecursor(A, *B)); 5490 PetscFunctionReturn(PETSC_SUCCESS); 5491 } 5492 5493 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5494 { 5495 PetscContainer rB; 5496 MatParentState *rb; 5497 5498 PetscFunctionBegin; 5499 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5500 PetscValidType(A, 1); 5501 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5502 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5503 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5504 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5505 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5506 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5507 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5508 PetscFunctionReturn(PETSC_SUCCESS); 5509 } 5510 5511 /*@ 5512 MatIsTranspose - Test whether a matrix is another one's transpose, 5513 or its own, in which case it tests symmetry. 5514 5515 Collective 5516 5517 Input Parameters: 5518 + A - the matrix to test 5519 . B - the matrix to test against, this can equal the first parameter 5520 - tol - tolerance, differences between entries smaller than this are counted as zero 5521 5522 Output Parameter: 5523 . flg - the result 5524 5525 Level: intermediate 5526 5527 Notes: 5528 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5529 test involves parallel copies of the block off-diagonal parts of the matrix. 5530 5531 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5532 @*/ 5533 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5534 { 5535 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5536 5537 PetscFunctionBegin; 5538 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5539 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5540 PetscAssertPointer(flg, 4); 5541 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5542 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5543 *flg = PETSC_FALSE; 5544 if (f && g) { 5545 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5546 PetscCall((*f)(A, B, tol, flg)); 5547 } else { 5548 MatType mattype; 5549 5550 PetscCall(MatGetType(f ? B : A, &mattype)); 5551 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5552 } 5553 PetscFunctionReturn(PETSC_SUCCESS); 5554 } 5555 5556 /*@ 5557 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5558 5559 Collective 5560 5561 Input Parameters: 5562 + mat - the matrix to transpose and complex conjugate 5563 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5564 5565 Output Parameter: 5566 . B - the Hermitian transpose 5567 5568 Level: intermediate 5569 5570 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5571 @*/ 5572 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5573 { 5574 PetscFunctionBegin; 5575 PetscCall(MatTranspose(mat, reuse, B)); 5576 #if defined(PETSC_USE_COMPLEX) 5577 PetscCall(MatConjugate(*B)); 5578 #endif 5579 PetscFunctionReturn(PETSC_SUCCESS); 5580 } 5581 5582 /*@ 5583 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5584 5585 Collective 5586 5587 Input Parameters: 5588 + A - the matrix to test 5589 . B - the matrix to test against, this can equal the first parameter 5590 - tol - tolerance, differences between entries smaller than this are counted as zero 5591 5592 Output Parameter: 5593 . flg - the result 5594 5595 Level: intermediate 5596 5597 Notes: 5598 Only available for `MATAIJ` matrices. 5599 5600 The sequential algorithm 5601 has a running time of the order of the number of nonzeros; the parallel 5602 test involves parallel copies of the block off-diagonal parts of the matrix. 5603 5604 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5605 @*/ 5606 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5607 { 5608 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5609 5610 PetscFunctionBegin; 5611 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5612 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5613 PetscAssertPointer(flg, 4); 5614 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5615 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5616 if (f && g) { 5617 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5618 PetscCall((*f)(A, B, tol, flg)); 5619 } 5620 PetscFunctionReturn(PETSC_SUCCESS); 5621 } 5622 5623 /*@ 5624 MatPermute - Creates a new matrix with rows and columns permuted from the 5625 original. 5626 5627 Collective 5628 5629 Input Parameters: 5630 + mat - the matrix to permute 5631 . row - row permutation, each processor supplies only the permutation for its rows 5632 - col - column permutation, each processor supplies only the permutation for its columns 5633 5634 Output Parameter: 5635 . B - the permuted matrix 5636 5637 Level: advanced 5638 5639 Note: 5640 The index sets map from row/col of permuted matrix to row/col of original matrix. 5641 The index sets should be on the same communicator as mat and have the same local sizes. 5642 5643 Developer Note: 5644 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5645 exploit the fact that row and col are permutations, consider implementing the 5646 more general `MatCreateSubMatrix()` instead. 5647 5648 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5649 @*/ 5650 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5651 { 5652 PetscFunctionBegin; 5653 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5654 PetscValidType(mat, 1); 5655 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5656 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5657 PetscAssertPointer(B, 4); 5658 PetscCheckSameComm(mat, 1, row, 2); 5659 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5660 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5661 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5662 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5663 MatCheckPreallocated(mat, 1); 5664 5665 if (mat->ops->permute) { 5666 PetscUseTypeMethod(mat, permute, row, col, B); 5667 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5668 } else { 5669 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5670 } 5671 PetscFunctionReturn(PETSC_SUCCESS); 5672 } 5673 5674 /*@ 5675 MatEqual - Compares two matrices. 5676 5677 Collective 5678 5679 Input Parameters: 5680 + A - the first matrix 5681 - B - the second matrix 5682 5683 Output Parameter: 5684 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5685 5686 Level: intermediate 5687 5688 .seealso: [](ch_matrices), `Mat` 5689 @*/ 5690 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5691 { 5692 PetscFunctionBegin; 5693 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5694 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5695 PetscValidType(A, 1); 5696 PetscValidType(B, 2); 5697 PetscAssertPointer(flg, 3); 5698 PetscCheckSameComm(A, 1, B, 2); 5699 MatCheckPreallocated(A, 1); 5700 MatCheckPreallocated(B, 2); 5701 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5702 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5703 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, 5704 B->cmap->N); 5705 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5706 PetscUseTypeMethod(A, equal, B, flg); 5707 } else { 5708 PetscCall(MatMultEqual(A, B, 10, flg)); 5709 } 5710 PetscFunctionReturn(PETSC_SUCCESS); 5711 } 5712 5713 /*@ 5714 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5715 matrices that are stored as vectors. Either of the two scaling 5716 matrices can be `NULL`. 5717 5718 Collective 5719 5720 Input Parameters: 5721 + mat - the matrix to be scaled 5722 . l - the left scaling vector (or `NULL`) 5723 - r - the right scaling vector (or `NULL`) 5724 5725 Level: intermediate 5726 5727 Note: 5728 `MatDiagonalScale()` computes $A = LAR$, where 5729 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5730 The L scales the rows of the matrix, the R scales the columns of the matrix. 5731 5732 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5733 @*/ 5734 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5735 { 5736 PetscFunctionBegin; 5737 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5738 PetscValidType(mat, 1); 5739 if (l) { 5740 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5741 PetscCheckSameComm(mat, 1, l, 2); 5742 } 5743 if (r) { 5744 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5745 PetscCheckSameComm(mat, 1, r, 3); 5746 } 5747 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5748 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5749 MatCheckPreallocated(mat, 1); 5750 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5751 5752 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5753 PetscUseTypeMethod(mat, diagonalscale, l, r); 5754 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5755 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5756 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5757 PetscFunctionReturn(PETSC_SUCCESS); 5758 } 5759 5760 /*@ 5761 MatScale - Scales all elements of a matrix by a given number. 5762 5763 Logically Collective 5764 5765 Input Parameters: 5766 + mat - the matrix to be scaled 5767 - a - the scaling value 5768 5769 Level: intermediate 5770 5771 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5772 @*/ 5773 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5774 { 5775 PetscFunctionBegin; 5776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5777 PetscValidType(mat, 1); 5778 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5779 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5780 PetscValidLogicalCollectiveScalar(mat, a, 2); 5781 MatCheckPreallocated(mat, 1); 5782 5783 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5784 if (a != (PetscScalar)1.0) { 5785 PetscUseTypeMethod(mat, scale, a); 5786 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5787 } 5788 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5789 PetscFunctionReturn(PETSC_SUCCESS); 5790 } 5791 5792 /*@ 5793 MatNorm - Calculates various norms of a matrix. 5794 5795 Collective 5796 5797 Input Parameters: 5798 + mat - the matrix 5799 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5800 5801 Output Parameter: 5802 . nrm - the resulting norm 5803 5804 Level: intermediate 5805 5806 .seealso: [](ch_matrices), `Mat` 5807 @*/ 5808 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5809 { 5810 PetscFunctionBegin; 5811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5812 PetscValidType(mat, 1); 5813 PetscAssertPointer(nrm, 3); 5814 5815 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5816 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5817 MatCheckPreallocated(mat, 1); 5818 5819 PetscUseTypeMethod(mat, norm, type, nrm); 5820 PetscFunctionReturn(PETSC_SUCCESS); 5821 } 5822 5823 /* 5824 This variable is used to prevent counting of MatAssemblyBegin() that 5825 are called from within a MatAssemblyEnd(). 5826 */ 5827 static PetscInt MatAssemblyEnd_InUse = 0; 5828 /*@ 5829 MatAssemblyBegin - Begins assembling the matrix. This routine should 5830 be called after completing all calls to `MatSetValues()`. 5831 5832 Collective 5833 5834 Input Parameters: 5835 + mat - the matrix 5836 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5837 5838 Level: beginner 5839 5840 Notes: 5841 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5842 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5843 5844 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5845 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5846 using the matrix. 5847 5848 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5849 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 5850 a global collective operation requiring all processes that share the matrix. 5851 5852 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5853 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5854 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5855 5856 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5857 @*/ 5858 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5859 { 5860 PetscFunctionBegin; 5861 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5862 PetscValidType(mat, 1); 5863 MatCheckPreallocated(mat, 1); 5864 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5865 if (mat->assembled) { 5866 mat->was_assembled = PETSC_TRUE; 5867 mat->assembled = PETSC_FALSE; 5868 } 5869 5870 if (!MatAssemblyEnd_InUse) { 5871 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5872 PetscTryTypeMethod(mat, assemblybegin, type); 5873 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5874 } else PetscTryTypeMethod(mat, assemblybegin, type); 5875 PetscFunctionReturn(PETSC_SUCCESS); 5876 } 5877 5878 /*@ 5879 MatAssembled - Indicates if a matrix has been assembled and is ready for 5880 use; for example, in matrix-vector product. 5881 5882 Not Collective 5883 5884 Input Parameter: 5885 . mat - the matrix 5886 5887 Output Parameter: 5888 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5889 5890 Level: advanced 5891 5892 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5893 @*/ 5894 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5895 { 5896 PetscFunctionBegin; 5897 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5898 PetscAssertPointer(assembled, 2); 5899 *assembled = mat->assembled; 5900 PetscFunctionReturn(PETSC_SUCCESS); 5901 } 5902 5903 /*@ 5904 MatAssemblyEnd - Completes assembling the matrix. This routine should 5905 be called after `MatAssemblyBegin()`. 5906 5907 Collective 5908 5909 Input Parameters: 5910 + mat - the matrix 5911 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5912 5913 Options Database Keys: 5914 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5915 . -mat_view ::ascii_info_detail - Prints more detailed info 5916 . -mat_view - Prints matrix in ASCII format 5917 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5918 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5919 . -display <name> - Sets display name (default is host) 5920 . -draw_pause <sec> - Sets number of seconds to pause after display 5921 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5922 . -viewer_socket_machine <machine> - Machine to use for socket 5923 . -viewer_socket_port <port> - Port number to use for socket 5924 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5925 5926 Level: beginner 5927 5928 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5929 @*/ 5930 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5931 { 5932 static PetscInt inassm = 0; 5933 PetscBool flg = PETSC_FALSE; 5934 5935 PetscFunctionBegin; 5936 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5937 PetscValidType(mat, 1); 5938 5939 inassm++; 5940 MatAssemblyEnd_InUse++; 5941 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5942 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5943 PetscTryTypeMethod(mat, assemblyend, type); 5944 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5945 } else PetscTryTypeMethod(mat, assemblyend, type); 5946 5947 /* Flush assembly is not a true assembly */ 5948 if (type != MAT_FLUSH_ASSEMBLY) { 5949 if (mat->num_ass) { 5950 if (!mat->symmetry_eternal) { 5951 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5952 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5953 } 5954 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5955 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5956 } 5957 mat->num_ass++; 5958 mat->assembled = PETSC_TRUE; 5959 mat->ass_nonzerostate = mat->nonzerostate; 5960 } 5961 5962 mat->insertmode = NOT_SET_VALUES; 5963 MatAssemblyEnd_InUse--; 5964 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5965 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5966 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5967 5968 if (mat->checksymmetryonassembly) { 5969 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5970 if (flg) { 5971 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5972 } else { 5973 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5974 } 5975 } 5976 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5977 } 5978 inassm--; 5979 PetscFunctionReturn(PETSC_SUCCESS); 5980 } 5981 5982 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5983 /*@ 5984 MatSetOption - Sets a parameter option for a matrix. Some options 5985 may be specific to certain storage formats. Some options 5986 determine how values will be inserted (or added). Sorted, 5987 row-oriented input will generally assemble the fastest. The default 5988 is row-oriented. 5989 5990 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5991 5992 Input Parameters: 5993 + mat - the matrix 5994 . op - the option, one of those listed below (and possibly others), 5995 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5996 5997 Options Describing Matrix Structure: 5998 + `MAT_SPD` - symmetric positive definite 5999 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 6000 . `MAT_HERMITIAN` - transpose is the complex conjugation 6001 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 6002 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 6003 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 6004 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 6005 6006 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 6007 do not need to be computed (usually at a high cost) 6008 6009 Options For Use with `MatSetValues()`: 6010 Insert a logically dense subblock, which can be 6011 . `MAT_ROW_ORIENTED` - row-oriented (default) 6012 6013 These options reflect the data you pass in with `MatSetValues()`; it has 6014 nothing to do with how the data is stored internally in the matrix 6015 data structure. 6016 6017 When (re)assembling a matrix, we can restrict the input for 6018 efficiency/debugging purposes. These options include 6019 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 6020 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 6021 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 6022 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 6023 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 6024 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 6025 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 6026 performance for very large process counts. 6027 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 6028 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 6029 functions, instead sending only neighbor messages. 6030 6031 Level: intermediate 6032 6033 Notes: 6034 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 6035 6036 Some options are relevant only for particular matrix types and 6037 are thus ignored by others. Other options are not supported by 6038 certain matrix types and will generate an error message if set. 6039 6040 If using Fortran to compute a matrix, one may need to 6041 use the column-oriented option (or convert to the row-oriented 6042 format). 6043 6044 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6045 that would generate a new entry in the nonzero structure is instead 6046 ignored. Thus, if memory has not already been allocated for this particular 6047 data, then the insertion is ignored. For dense matrices, in which 6048 the entire array is allocated, no entries are ever ignored. 6049 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6050 6051 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6052 that would generate a new entry in the nonzero structure instead produces 6053 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 6054 6055 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6056 that would generate a new entry that has not been preallocated will 6057 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6058 only.) This is a useful flag when debugging matrix memory preallocation. 6059 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6060 6061 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6062 other processors should be dropped, rather than stashed. 6063 This is useful if you know that the "owning" processor is also 6064 always generating the correct matrix entries, so that PETSc need 6065 not transfer duplicate entries generated on another processor. 6066 6067 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6068 searches during matrix assembly. When this flag is set, the hash table 6069 is created during the first matrix assembly. This hash table is 6070 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6071 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6072 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6073 supported by `MATMPIBAIJ` format only. 6074 6075 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6076 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6077 6078 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6079 a zero location in the matrix 6080 6081 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6082 6083 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6084 zero row routines and thus improves performance for very large process counts. 6085 6086 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6087 part of the matrix (since they should match the upper triangular part). 6088 6089 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6090 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6091 with finite difference schemes with non-periodic boundary conditions. 6092 6093 Developer Note: 6094 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6095 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6096 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6097 not changed. 6098 6099 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6100 @*/ 6101 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6102 { 6103 PetscFunctionBegin; 6104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6105 if (op > 0) { 6106 PetscValidLogicalCollectiveEnum(mat, op, 2); 6107 PetscValidLogicalCollectiveBool(mat, flg, 3); 6108 } 6109 6110 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); 6111 6112 switch (op) { 6113 case MAT_FORCE_DIAGONAL_ENTRIES: 6114 mat->force_diagonals = flg; 6115 PetscFunctionReturn(PETSC_SUCCESS); 6116 case MAT_NO_OFF_PROC_ENTRIES: 6117 mat->nooffprocentries = flg; 6118 PetscFunctionReturn(PETSC_SUCCESS); 6119 case MAT_SUBSET_OFF_PROC_ENTRIES: 6120 mat->assembly_subset = flg; 6121 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6122 #if !defined(PETSC_HAVE_MPIUNI) 6123 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6124 #endif 6125 mat->stash.first_assembly_done = PETSC_FALSE; 6126 } 6127 PetscFunctionReturn(PETSC_SUCCESS); 6128 case MAT_NO_OFF_PROC_ZERO_ROWS: 6129 mat->nooffproczerorows = flg; 6130 PetscFunctionReturn(PETSC_SUCCESS); 6131 case MAT_SPD: 6132 if (flg) { 6133 mat->spd = PETSC_BOOL3_TRUE; 6134 mat->symmetric = PETSC_BOOL3_TRUE; 6135 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6136 } else { 6137 mat->spd = PETSC_BOOL3_FALSE; 6138 } 6139 break; 6140 case MAT_SYMMETRIC: 6141 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6142 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6143 #if !defined(PETSC_USE_COMPLEX) 6144 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6145 #endif 6146 break; 6147 case MAT_HERMITIAN: 6148 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6149 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6150 #if !defined(PETSC_USE_COMPLEX) 6151 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6152 #endif 6153 break; 6154 case MAT_STRUCTURALLY_SYMMETRIC: 6155 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6156 break; 6157 case MAT_SYMMETRY_ETERNAL: 6158 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"); 6159 mat->symmetry_eternal = flg; 6160 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6161 break; 6162 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6163 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"); 6164 mat->structural_symmetry_eternal = flg; 6165 break; 6166 case MAT_SPD_ETERNAL: 6167 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"); 6168 mat->spd_eternal = flg; 6169 if (flg) { 6170 mat->structural_symmetry_eternal = PETSC_TRUE; 6171 mat->symmetry_eternal = PETSC_TRUE; 6172 } 6173 break; 6174 case MAT_STRUCTURE_ONLY: 6175 mat->structure_only = flg; 6176 break; 6177 case MAT_SORTED_FULL: 6178 mat->sortedfull = flg; 6179 break; 6180 default: 6181 break; 6182 } 6183 PetscTryTypeMethod(mat, setoption, op, flg); 6184 PetscFunctionReturn(PETSC_SUCCESS); 6185 } 6186 6187 /*@ 6188 MatGetOption - Gets a parameter option that has been set for a matrix. 6189 6190 Logically Collective 6191 6192 Input Parameters: 6193 + mat - the matrix 6194 - op - the option, this only responds to certain options, check the code for which ones 6195 6196 Output Parameter: 6197 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6198 6199 Level: intermediate 6200 6201 Notes: 6202 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6203 6204 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6205 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6206 6207 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6208 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6209 @*/ 6210 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6211 { 6212 PetscFunctionBegin; 6213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6214 PetscValidType(mat, 1); 6215 6216 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); 6217 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()"); 6218 6219 switch (op) { 6220 case MAT_NO_OFF_PROC_ENTRIES: 6221 *flg = mat->nooffprocentries; 6222 break; 6223 case MAT_NO_OFF_PROC_ZERO_ROWS: 6224 *flg = mat->nooffproczerorows; 6225 break; 6226 case MAT_SYMMETRIC: 6227 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6228 break; 6229 case MAT_HERMITIAN: 6230 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6231 break; 6232 case MAT_STRUCTURALLY_SYMMETRIC: 6233 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6234 break; 6235 case MAT_SPD: 6236 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6237 break; 6238 case MAT_SYMMETRY_ETERNAL: 6239 *flg = mat->symmetry_eternal; 6240 break; 6241 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6242 *flg = mat->symmetry_eternal; 6243 break; 6244 default: 6245 break; 6246 } 6247 PetscFunctionReturn(PETSC_SUCCESS); 6248 } 6249 6250 /*@ 6251 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6252 this routine retains the old nonzero structure. 6253 6254 Logically Collective 6255 6256 Input Parameter: 6257 . mat - the matrix 6258 6259 Level: intermediate 6260 6261 Note: 6262 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. 6263 See the Performance chapter of the users manual for information on preallocating matrices. 6264 6265 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6266 @*/ 6267 PetscErrorCode MatZeroEntries(Mat mat) 6268 { 6269 PetscFunctionBegin; 6270 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6271 PetscValidType(mat, 1); 6272 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6273 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"); 6274 MatCheckPreallocated(mat, 1); 6275 6276 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6277 PetscUseTypeMethod(mat, zeroentries); 6278 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6279 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6280 PetscFunctionReturn(PETSC_SUCCESS); 6281 } 6282 6283 /*@ 6284 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6285 of a set of rows and columns of a matrix. 6286 6287 Collective 6288 6289 Input Parameters: 6290 + mat - the matrix 6291 . numRows - the number of rows/columns to zero 6292 . rows - the global row indices 6293 . diag - value put in the diagonal of the eliminated rows 6294 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6295 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6296 6297 Level: intermediate 6298 6299 Notes: 6300 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6301 6302 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6303 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 6304 6305 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6306 Krylov method to take advantage of the known solution on the zeroed rows. 6307 6308 For the parallel case, all processes that share the matrix (i.e., 6309 those in the communicator used for matrix creation) MUST call this 6310 routine, regardless of whether any rows being zeroed are owned by 6311 them. 6312 6313 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6314 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 6315 missing. 6316 6317 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6318 list only rows local to itself). 6319 6320 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6321 6322 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6323 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6324 @*/ 6325 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6326 { 6327 PetscFunctionBegin; 6328 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6329 PetscValidType(mat, 1); 6330 if (numRows) PetscAssertPointer(rows, 3); 6331 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6332 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6333 MatCheckPreallocated(mat, 1); 6334 6335 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6336 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6337 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6338 PetscFunctionReturn(PETSC_SUCCESS); 6339 } 6340 6341 /*@ 6342 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6343 of a set of rows and columns of a matrix. 6344 6345 Collective 6346 6347 Input Parameters: 6348 + mat - the matrix 6349 . is - the rows to zero 6350 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6351 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6352 - b - optional vector of right-hand side, that will be adjusted by provided solution 6353 6354 Level: intermediate 6355 6356 Note: 6357 See `MatZeroRowsColumns()` for details on how this routine operates. 6358 6359 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6360 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6361 @*/ 6362 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6363 { 6364 PetscInt numRows; 6365 const PetscInt *rows; 6366 6367 PetscFunctionBegin; 6368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6369 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6370 PetscValidType(mat, 1); 6371 PetscValidType(is, 2); 6372 PetscCall(ISGetLocalSize(is, &numRows)); 6373 PetscCall(ISGetIndices(is, &rows)); 6374 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6375 PetscCall(ISRestoreIndices(is, &rows)); 6376 PetscFunctionReturn(PETSC_SUCCESS); 6377 } 6378 6379 /*@ 6380 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6381 of a set of rows of a matrix. 6382 6383 Collective 6384 6385 Input Parameters: 6386 + mat - the matrix 6387 . numRows - the number of rows to zero 6388 . rows - the global row indices 6389 . diag - value put in the diagonal of the zeroed rows 6390 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6391 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6392 6393 Level: intermediate 6394 6395 Notes: 6396 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6397 6398 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6399 6400 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6401 Krylov method to take advantage of the known solution on the zeroed rows. 6402 6403 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) 6404 from the matrix. 6405 6406 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6407 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 6408 formats this does not alter the nonzero structure. 6409 6410 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6411 of the matrix is not changed the values are 6412 merely zeroed. 6413 6414 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6415 formats can optionally remove the main diagonal entry from the 6416 nonzero structure as well, by passing 0.0 as the final argument). 6417 6418 For the parallel case, all processes that share the matrix (i.e., 6419 those in the communicator used for matrix creation) MUST call this 6420 routine, regardless of whether any rows being zeroed are owned by 6421 them. 6422 6423 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6424 list only rows local to itself). 6425 6426 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6427 owns that are to be zeroed. This saves a global synchronization in the implementation. 6428 6429 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6430 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6431 @*/ 6432 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6433 { 6434 PetscFunctionBegin; 6435 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6436 PetscValidType(mat, 1); 6437 if (numRows) PetscAssertPointer(rows, 3); 6438 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6439 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6440 MatCheckPreallocated(mat, 1); 6441 6442 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6443 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6444 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6445 PetscFunctionReturn(PETSC_SUCCESS); 6446 } 6447 6448 /*@ 6449 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6450 of a set of rows of a matrix. 6451 6452 Collective 6453 6454 Input Parameters: 6455 + mat - the matrix 6456 . is - index set of rows to remove (if `NULL` then no row is removed) 6457 . diag - value put in all diagonals of eliminated rows 6458 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6459 - b - optional vector of right-hand side, that will be adjusted by provided solution 6460 6461 Level: intermediate 6462 6463 Note: 6464 See `MatZeroRows()` for details on how this routine operates. 6465 6466 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6467 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6468 @*/ 6469 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6470 { 6471 PetscInt numRows = 0; 6472 const PetscInt *rows = NULL; 6473 6474 PetscFunctionBegin; 6475 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6476 PetscValidType(mat, 1); 6477 if (is) { 6478 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6479 PetscCall(ISGetLocalSize(is, &numRows)); 6480 PetscCall(ISGetIndices(is, &rows)); 6481 } 6482 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6483 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6484 PetscFunctionReturn(PETSC_SUCCESS); 6485 } 6486 6487 /*@ 6488 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6489 of a set of rows of a matrix. These rows must be local to the process. 6490 6491 Collective 6492 6493 Input Parameters: 6494 + mat - the matrix 6495 . numRows - the number of rows to remove 6496 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6497 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6498 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6499 - b - optional vector of right-hand side, that will be adjusted by provided solution 6500 6501 Level: intermediate 6502 6503 Notes: 6504 See `MatZeroRows()` for details on how this routine operates. 6505 6506 The grid coordinates are across the entire grid, not just the local portion 6507 6508 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6509 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6510 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6511 `DM_BOUNDARY_PERIODIC` boundary type. 6512 6513 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 6514 a single value per point) you can skip filling those indices. 6515 6516 Fortran Note: 6517 `idxm` and `idxn` should be declared as 6518 $ MatStencil idxm(4, m) 6519 and the values inserted using 6520 .vb 6521 idxm(MatStencil_i, 1) = i 6522 idxm(MatStencil_j, 1) = j 6523 idxm(MatStencil_k, 1) = k 6524 idxm(MatStencil_c, 1) = c 6525 etc 6526 .ve 6527 6528 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6529 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6530 @*/ 6531 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6532 { 6533 PetscInt dim = mat->stencil.dim; 6534 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6535 PetscInt *dims = mat->stencil.dims + 1; 6536 PetscInt *starts = mat->stencil.starts; 6537 PetscInt *dxm = (PetscInt *)rows; 6538 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6539 6540 PetscFunctionBegin; 6541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6542 PetscValidType(mat, 1); 6543 if (numRows) PetscAssertPointer(rows, 3); 6544 6545 PetscCall(PetscMalloc1(numRows, &jdxm)); 6546 for (i = 0; i < numRows; ++i) { 6547 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6548 for (j = 0; j < 3 - sdim; ++j) dxm++; 6549 /* Local index in X dir */ 6550 tmp = *dxm++ - starts[0]; 6551 /* Loop over remaining dimensions */ 6552 for (j = 0; j < dim - 1; ++j) { 6553 /* If nonlocal, set index to be negative */ 6554 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6555 /* Update local index */ 6556 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6557 } 6558 /* Skip component slot if necessary */ 6559 if (mat->stencil.noc) dxm++; 6560 /* Local row number */ 6561 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6562 } 6563 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6564 PetscCall(PetscFree(jdxm)); 6565 PetscFunctionReturn(PETSC_SUCCESS); 6566 } 6567 6568 /*@ 6569 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6570 of a set of rows and columns of a matrix. 6571 6572 Collective 6573 6574 Input Parameters: 6575 + mat - the matrix 6576 . numRows - the number of rows/columns to remove 6577 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6578 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6579 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6580 - b - optional vector of right-hand side, that will be adjusted by provided solution 6581 6582 Level: intermediate 6583 6584 Notes: 6585 See `MatZeroRowsColumns()` for details on how this routine operates. 6586 6587 The grid coordinates are across the entire grid, not just the local portion 6588 6589 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6590 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6591 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6592 `DM_BOUNDARY_PERIODIC` boundary type. 6593 6594 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 6595 a single value per point) you can skip filling those indices. 6596 6597 Fortran Note: 6598 `idxm` and `idxn` should be declared as 6599 $ MatStencil idxm(4, m) 6600 and the values inserted using 6601 .vb 6602 idxm(MatStencil_i, 1) = i 6603 idxm(MatStencil_j, 1) = j 6604 idxm(MatStencil_k, 1) = k 6605 idxm(MatStencil_c, 1) = c 6606 etc 6607 .ve 6608 6609 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6610 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6611 @*/ 6612 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6613 { 6614 PetscInt dim = mat->stencil.dim; 6615 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6616 PetscInt *dims = mat->stencil.dims + 1; 6617 PetscInt *starts = mat->stencil.starts; 6618 PetscInt *dxm = (PetscInt *)rows; 6619 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6620 6621 PetscFunctionBegin; 6622 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6623 PetscValidType(mat, 1); 6624 if (numRows) PetscAssertPointer(rows, 3); 6625 6626 PetscCall(PetscMalloc1(numRows, &jdxm)); 6627 for (i = 0; i < numRows; ++i) { 6628 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6629 for (j = 0; j < 3 - sdim; ++j) dxm++; 6630 /* Local index in X dir */ 6631 tmp = *dxm++ - starts[0]; 6632 /* Loop over remaining dimensions */ 6633 for (j = 0; j < dim - 1; ++j) { 6634 /* If nonlocal, set index to be negative */ 6635 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6636 /* Update local index */ 6637 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6638 } 6639 /* Skip component slot if necessary */ 6640 if (mat->stencil.noc) dxm++; 6641 /* Local row number */ 6642 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6643 } 6644 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6645 PetscCall(PetscFree(jdxm)); 6646 PetscFunctionReturn(PETSC_SUCCESS); 6647 } 6648 6649 /*@ 6650 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6651 of a set of rows of a matrix; using local numbering of rows. 6652 6653 Collective 6654 6655 Input Parameters: 6656 + mat - the matrix 6657 . numRows - the number of rows to remove 6658 . rows - the local row indices 6659 . diag - value put in all diagonals of eliminated rows 6660 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6661 - b - optional vector of right-hand side, that will be adjusted by provided solution 6662 6663 Level: intermediate 6664 6665 Notes: 6666 Before calling `MatZeroRowsLocal()`, the user must first set the 6667 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6668 6669 See `MatZeroRows()` for details on how this routine operates. 6670 6671 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6672 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6673 @*/ 6674 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6675 { 6676 PetscFunctionBegin; 6677 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6678 PetscValidType(mat, 1); 6679 if (numRows) PetscAssertPointer(rows, 3); 6680 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6681 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6682 MatCheckPreallocated(mat, 1); 6683 6684 if (mat->ops->zerorowslocal) { 6685 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6686 } else { 6687 IS is, newis; 6688 const PetscInt *newRows; 6689 6690 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6691 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6692 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6693 PetscCall(ISGetIndices(newis, &newRows)); 6694 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6695 PetscCall(ISRestoreIndices(newis, &newRows)); 6696 PetscCall(ISDestroy(&newis)); 6697 PetscCall(ISDestroy(&is)); 6698 } 6699 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6700 PetscFunctionReturn(PETSC_SUCCESS); 6701 } 6702 6703 /*@ 6704 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6705 of a set of rows of a matrix; using local numbering of rows. 6706 6707 Collective 6708 6709 Input Parameters: 6710 + mat - the matrix 6711 . is - index set of rows to remove 6712 . diag - value put in all diagonals of eliminated rows 6713 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6714 - b - optional vector of right-hand side, that will be adjusted by provided solution 6715 6716 Level: intermediate 6717 6718 Notes: 6719 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6720 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6721 6722 See `MatZeroRows()` for details on how this routine operates. 6723 6724 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6725 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6726 @*/ 6727 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6728 { 6729 PetscInt numRows; 6730 const PetscInt *rows; 6731 6732 PetscFunctionBegin; 6733 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6734 PetscValidType(mat, 1); 6735 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6736 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6737 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6738 MatCheckPreallocated(mat, 1); 6739 6740 PetscCall(ISGetLocalSize(is, &numRows)); 6741 PetscCall(ISGetIndices(is, &rows)); 6742 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6743 PetscCall(ISRestoreIndices(is, &rows)); 6744 PetscFunctionReturn(PETSC_SUCCESS); 6745 } 6746 6747 /*@ 6748 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6749 of a set of rows and columns of a matrix; using local numbering of rows. 6750 6751 Collective 6752 6753 Input Parameters: 6754 + mat - the matrix 6755 . numRows - the number of rows to remove 6756 . rows - the global row indices 6757 . diag - value put in all diagonals of eliminated rows 6758 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6759 - b - optional vector of right-hand side, that will be adjusted by provided solution 6760 6761 Level: intermediate 6762 6763 Notes: 6764 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6765 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6766 6767 See `MatZeroRowsColumns()` for details on how this routine operates. 6768 6769 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6770 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6771 @*/ 6772 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6773 { 6774 IS is, newis; 6775 const PetscInt *newRows; 6776 6777 PetscFunctionBegin; 6778 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6779 PetscValidType(mat, 1); 6780 if (numRows) PetscAssertPointer(rows, 3); 6781 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6782 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6783 MatCheckPreallocated(mat, 1); 6784 6785 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6786 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6787 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6788 PetscCall(ISGetIndices(newis, &newRows)); 6789 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6790 PetscCall(ISRestoreIndices(newis, &newRows)); 6791 PetscCall(ISDestroy(&newis)); 6792 PetscCall(ISDestroy(&is)); 6793 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6794 PetscFunctionReturn(PETSC_SUCCESS); 6795 } 6796 6797 /*@ 6798 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6799 of a set of rows and columns of a matrix; using local numbering of rows. 6800 6801 Collective 6802 6803 Input Parameters: 6804 + mat - the matrix 6805 . is - index set of rows to remove 6806 . diag - value put in all diagonals of eliminated rows 6807 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6808 - b - optional vector of right-hand side, that will be adjusted by provided solution 6809 6810 Level: intermediate 6811 6812 Notes: 6813 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6814 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6815 6816 See `MatZeroRowsColumns()` for details on how this routine operates. 6817 6818 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6819 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6820 @*/ 6821 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6822 { 6823 PetscInt numRows; 6824 const PetscInt *rows; 6825 6826 PetscFunctionBegin; 6827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6828 PetscValidType(mat, 1); 6829 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6830 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6831 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6832 MatCheckPreallocated(mat, 1); 6833 6834 PetscCall(ISGetLocalSize(is, &numRows)); 6835 PetscCall(ISGetIndices(is, &rows)); 6836 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6837 PetscCall(ISRestoreIndices(is, &rows)); 6838 PetscFunctionReturn(PETSC_SUCCESS); 6839 } 6840 6841 /*@ 6842 MatGetSize - Returns the numbers of rows and columns in a matrix. 6843 6844 Not Collective 6845 6846 Input Parameter: 6847 . mat - the matrix 6848 6849 Output Parameters: 6850 + m - the number of global rows 6851 - n - the number of global columns 6852 6853 Level: beginner 6854 6855 Note: 6856 Both output parameters can be `NULL` on input. 6857 6858 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6859 @*/ 6860 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6861 { 6862 PetscFunctionBegin; 6863 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6864 if (m) *m = mat->rmap->N; 6865 if (n) *n = mat->cmap->N; 6866 PetscFunctionReturn(PETSC_SUCCESS); 6867 } 6868 6869 /*@ 6870 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6871 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6872 6873 Not Collective 6874 6875 Input Parameter: 6876 . mat - the matrix 6877 6878 Output Parameters: 6879 + m - the number of local rows, use `NULL` to not obtain this value 6880 - n - the number of local columns, use `NULL` to not obtain this value 6881 6882 Level: beginner 6883 6884 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6885 @*/ 6886 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6887 { 6888 PetscFunctionBegin; 6889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6890 if (m) PetscAssertPointer(m, 2); 6891 if (n) PetscAssertPointer(n, 3); 6892 if (m) *m = mat->rmap->n; 6893 if (n) *n = mat->cmap->n; 6894 PetscFunctionReturn(PETSC_SUCCESS); 6895 } 6896 6897 /*@ 6898 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6899 vector one multiplies this matrix by that are owned by this processor. 6900 6901 Not Collective, unless matrix has not been allocated, then collective 6902 6903 Input Parameter: 6904 . mat - the matrix 6905 6906 Output Parameters: 6907 + m - the global index of the first local column, use `NULL` to not obtain this value 6908 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6909 6910 Level: developer 6911 6912 Notes: 6913 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6914 6915 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6916 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6917 6918 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6919 the local values in the matrix. 6920 6921 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6922 Layouts](sec_matlayout) for details on matrix layouts. 6923 6924 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6925 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6926 @*/ 6927 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6928 { 6929 PetscFunctionBegin; 6930 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6931 PetscValidType(mat, 1); 6932 if (m) PetscAssertPointer(m, 2); 6933 if (n) PetscAssertPointer(n, 3); 6934 MatCheckPreallocated(mat, 1); 6935 if (m) *m = mat->cmap->rstart; 6936 if (n) *n = mat->cmap->rend; 6937 PetscFunctionReturn(PETSC_SUCCESS); 6938 } 6939 6940 /*@ 6941 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6942 this MPI process. 6943 6944 Not Collective 6945 6946 Input Parameter: 6947 . mat - the matrix 6948 6949 Output Parameters: 6950 + m - the global index of the first local row, use `NULL` to not obtain this value 6951 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6952 6953 Level: beginner 6954 6955 Notes: 6956 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6957 6958 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6959 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6960 6961 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6962 the local values in the matrix. 6963 6964 The high argument is one more than the last element stored locally. 6965 6966 For all matrices it returns the range of matrix rows associated with rows of a vector that 6967 would contain the result of a matrix vector product with this matrix. See [Matrix 6968 Layouts](sec_matlayout) for details on matrix layouts. 6969 6970 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6971 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6972 @*/ 6973 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6974 { 6975 PetscFunctionBegin; 6976 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6977 PetscValidType(mat, 1); 6978 if (m) PetscAssertPointer(m, 2); 6979 if (n) PetscAssertPointer(n, 3); 6980 MatCheckPreallocated(mat, 1); 6981 if (m) *m = mat->rmap->rstart; 6982 if (n) *n = mat->rmap->rend; 6983 PetscFunctionReturn(PETSC_SUCCESS); 6984 } 6985 6986 /*@C 6987 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6988 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6989 6990 Not Collective, unless matrix has not been allocated 6991 6992 Input Parameter: 6993 . mat - the matrix 6994 6995 Output Parameter: 6996 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6997 where `size` is the number of MPI processes used by `mat` 6998 6999 Level: beginner 7000 7001 Notes: 7002 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7003 7004 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7005 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7006 7007 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7008 the local values in the matrix. 7009 7010 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 7011 would contain the result of a matrix vector product with this matrix. See [Matrix 7012 Layouts](sec_matlayout) for details on matrix layouts. 7013 7014 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 7015 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 7016 `DMDAGetGhostCorners()`, `DM` 7017 @*/ 7018 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 7019 { 7020 PetscFunctionBegin; 7021 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7022 PetscValidType(mat, 1); 7023 MatCheckPreallocated(mat, 1); 7024 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 7025 PetscFunctionReturn(PETSC_SUCCESS); 7026 } 7027 7028 /*@C 7029 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 7030 vector one multiplies this vector by that are owned by each processor. 7031 7032 Not Collective, unless matrix has not been allocated 7033 7034 Input Parameter: 7035 . mat - the matrix 7036 7037 Output Parameter: 7038 . ranges - start of each processors portion plus one more than the total length at the end 7039 7040 Level: beginner 7041 7042 Notes: 7043 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7044 7045 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7046 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7047 7048 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7049 the local values in the matrix. 7050 7051 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7052 Layouts](sec_matlayout) for details on matrix layouts. 7053 7054 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7055 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7056 `DMDAGetGhostCorners()`, `DM` 7057 @*/ 7058 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7059 { 7060 PetscFunctionBegin; 7061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7062 PetscValidType(mat, 1); 7063 MatCheckPreallocated(mat, 1); 7064 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7065 PetscFunctionReturn(PETSC_SUCCESS); 7066 } 7067 7068 /*@ 7069 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7070 7071 Not Collective 7072 7073 Input Parameter: 7074 . A - matrix 7075 7076 Output Parameters: 7077 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7078 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7079 7080 Level: intermediate 7081 7082 Note: 7083 You should call `ISDestroy()` on the returned `IS` 7084 7085 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7086 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7087 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7088 details on matrix layouts. 7089 7090 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7091 @*/ 7092 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7093 { 7094 PetscErrorCode (*f)(Mat, IS *, IS *); 7095 7096 PetscFunctionBegin; 7097 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7098 PetscValidType(A, 1); 7099 MatCheckPreallocated(A, 1); 7100 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7101 if (f) { 7102 PetscCall((*f)(A, rows, cols)); 7103 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7104 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7105 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7106 } 7107 PetscFunctionReturn(PETSC_SUCCESS); 7108 } 7109 7110 /*@ 7111 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7112 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7113 to complete the factorization. 7114 7115 Collective 7116 7117 Input Parameters: 7118 + fact - the factorized matrix obtained with `MatGetFactor()` 7119 . mat - the matrix 7120 . row - row permutation 7121 . col - column permutation 7122 - info - structure containing 7123 .vb 7124 levels - number of levels of fill. 7125 expected fill - as ratio of original fill. 7126 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7127 missing diagonal entries) 7128 .ve 7129 7130 Level: developer 7131 7132 Notes: 7133 See [Matrix Factorization](sec_matfactor) for additional information. 7134 7135 Most users should employ the `KSP` interface for linear solvers 7136 instead of working directly with matrix algebra routines such as this. 7137 See, e.g., `KSPCreate()`. 7138 7139 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7140 7141 Developer Note: 7142 The Fortran interface is not autogenerated as the 7143 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7144 7145 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7146 `MatGetOrdering()`, `MatFactorInfo` 7147 @*/ 7148 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7149 { 7150 PetscFunctionBegin; 7151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7152 PetscValidType(mat, 2); 7153 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7154 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7155 PetscAssertPointer(info, 5); 7156 PetscAssertPointer(fact, 1); 7157 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7158 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7159 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7160 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7161 MatCheckPreallocated(mat, 2); 7162 7163 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7164 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7165 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7166 PetscFunctionReturn(PETSC_SUCCESS); 7167 } 7168 7169 /*@ 7170 MatICCFactorSymbolic - Performs symbolic incomplete 7171 Cholesky factorization for a symmetric matrix. Use 7172 `MatCholeskyFactorNumeric()` to complete the factorization. 7173 7174 Collective 7175 7176 Input Parameters: 7177 + fact - the factorized matrix obtained with `MatGetFactor()` 7178 . mat - the matrix to be factored 7179 . perm - row and column permutation 7180 - info - structure containing 7181 .vb 7182 levels - number of levels of fill. 7183 expected fill - as ratio of original fill. 7184 .ve 7185 7186 Level: developer 7187 7188 Notes: 7189 Most users should employ the `KSP` interface for linear solvers 7190 instead of working directly with matrix algebra routines such as this. 7191 See, e.g., `KSPCreate()`. 7192 7193 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7194 7195 Developer Note: 7196 The Fortran interface is not autogenerated as the 7197 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7198 7199 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7200 @*/ 7201 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7202 { 7203 PetscFunctionBegin; 7204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7205 PetscValidType(mat, 2); 7206 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7207 PetscAssertPointer(info, 4); 7208 PetscAssertPointer(fact, 1); 7209 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7210 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7211 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7212 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7213 MatCheckPreallocated(mat, 2); 7214 7215 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7216 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7217 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7218 PetscFunctionReturn(PETSC_SUCCESS); 7219 } 7220 7221 /*@C 7222 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7223 points to an array of valid matrices, they may be reused to store the new 7224 submatrices. 7225 7226 Collective 7227 7228 Input Parameters: 7229 + mat - the matrix 7230 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7231 . irow - index set of rows to extract 7232 . icol - index set of columns to extract 7233 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7234 7235 Output Parameter: 7236 . submat - the array of submatrices 7237 7238 Level: advanced 7239 7240 Notes: 7241 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7242 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7243 to extract a parallel submatrix. 7244 7245 Some matrix types place restrictions on the row and column 7246 indices, such as that they be sorted or that they be equal to each other. 7247 7248 The index sets may not have duplicate entries. 7249 7250 When extracting submatrices from a parallel matrix, each processor can 7251 form a different submatrix by setting the rows and columns of its 7252 individual index sets according to the local submatrix desired. 7253 7254 When finished using the submatrices, the user should destroy 7255 them with `MatDestroySubMatrices()`. 7256 7257 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7258 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7259 7260 This routine creates the matrices in submat; you should NOT create them before 7261 calling it. It also allocates the array of matrix pointers submat. 7262 7263 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7264 request one row/column in a block, they must request all rows/columns that are in 7265 that block. For example, if the block size is 2 you cannot request just row 0 and 7266 column 0. 7267 7268 Fortran Note: 7269 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7270 7271 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7272 @*/ 7273 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7274 { 7275 PetscInt i; 7276 PetscBool eq; 7277 7278 PetscFunctionBegin; 7279 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7280 PetscValidType(mat, 1); 7281 if (n) { 7282 PetscAssertPointer(irow, 3); 7283 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7284 PetscAssertPointer(icol, 4); 7285 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7286 } 7287 PetscAssertPointer(submat, 6); 7288 if (n && scall == MAT_REUSE_MATRIX) { 7289 PetscAssertPointer(*submat, 6); 7290 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7291 } 7292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7294 MatCheckPreallocated(mat, 1); 7295 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7296 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7297 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7298 for (i = 0; i < n; i++) { 7299 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7300 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7301 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7302 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7303 if (mat->boundtocpu && mat->bindingpropagates) { 7304 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7305 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7306 } 7307 #endif 7308 } 7309 PetscFunctionReturn(PETSC_SUCCESS); 7310 } 7311 7312 /*@C 7313 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7314 7315 Collective 7316 7317 Input Parameters: 7318 + mat - the matrix 7319 . n - the number of submatrixes to be extracted 7320 . irow - index set of rows to extract 7321 . icol - index set of columns to extract 7322 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7323 7324 Output Parameter: 7325 . submat - the array of submatrices 7326 7327 Level: advanced 7328 7329 Note: 7330 This is used by `PCGASM` 7331 7332 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7333 @*/ 7334 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7335 { 7336 PetscInt i; 7337 PetscBool eq; 7338 7339 PetscFunctionBegin; 7340 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7341 PetscValidType(mat, 1); 7342 if (n) { 7343 PetscAssertPointer(irow, 3); 7344 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7345 PetscAssertPointer(icol, 4); 7346 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7347 } 7348 PetscAssertPointer(submat, 6); 7349 if (n && scall == MAT_REUSE_MATRIX) { 7350 PetscAssertPointer(*submat, 6); 7351 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7352 } 7353 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7354 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7355 MatCheckPreallocated(mat, 1); 7356 7357 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7358 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7359 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7360 for (i = 0; i < n; i++) { 7361 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7362 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7363 } 7364 PetscFunctionReturn(PETSC_SUCCESS); 7365 } 7366 7367 /*@C 7368 MatDestroyMatrices - Destroys an array of matrices. 7369 7370 Collective 7371 7372 Input Parameters: 7373 + n - the number of local matrices 7374 - mat - the matrices (this is a pointer to the array of matrices) 7375 7376 Level: advanced 7377 7378 Notes: 7379 Frees not only the matrices, but also the array that contains the matrices 7380 7381 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7382 7383 Fortran Note: 7384 Does not free the `mat` array. 7385 7386 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7387 @*/ 7388 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7389 { 7390 PetscInt i; 7391 7392 PetscFunctionBegin; 7393 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7394 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7395 PetscAssertPointer(mat, 2); 7396 7397 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7398 7399 /* memory is allocated even if n = 0 */ 7400 PetscCall(PetscFree(*mat)); 7401 PetscFunctionReturn(PETSC_SUCCESS); 7402 } 7403 7404 /*@C 7405 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7406 7407 Collective 7408 7409 Input Parameters: 7410 + n - the number of local matrices 7411 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7412 sequence of `MatCreateSubMatrices()`) 7413 7414 Level: advanced 7415 7416 Note: 7417 Frees not only the matrices, but also the array that contains the matrices 7418 7419 Fortran Note: 7420 Does not free the `mat` array. 7421 7422 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7423 @*/ 7424 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7425 { 7426 Mat mat0; 7427 7428 PetscFunctionBegin; 7429 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7430 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7431 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7432 PetscAssertPointer(mat, 2); 7433 7434 mat0 = (*mat)[0]; 7435 if (mat0 && mat0->ops->destroysubmatrices) { 7436 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7437 } else { 7438 PetscCall(MatDestroyMatrices(n, mat)); 7439 } 7440 PetscFunctionReturn(PETSC_SUCCESS); 7441 } 7442 7443 /*@ 7444 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7445 7446 Collective 7447 7448 Input Parameter: 7449 . mat - the matrix 7450 7451 Output Parameter: 7452 . matstruct - the sequential matrix with the nonzero structure of `mat` 7453 7454 Level: developer 7455 7456 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7457 @*/ 7458 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7459 { 7460 PetscFunctionBegin; 7461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7462 PetscAssertPointer(matstruct, 2); 7463 7464 PetscValidType(mat, 1); 7465 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7466 MatCheckPreallocated(mat, 1); 7467 7468 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7469 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7470 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7471 PetscFunctionReturn(PETSC_SUCCESS); 7472 } 7473 7474 /*@C 7475 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7476 7477 Collective 7478 7479 Input Parameter: 7480 . mat - the matrix 7481 7482 Level: advanced 7483 7484 Note: 7485 This is not needed, one can just call `MatDestroy()` 7486 7487 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7488 @*/ 7489 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7490 { 7491 PetscFunctionBegin; 7492 PetscAssertPointer(mat, 1); 7493 PetscCall(MatDestroy(mat)); 7494 PetscFunctionReturn(PETSC_SUCCESS); 7495 } 7496 7497 /*@ 7498 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7499 replaces the index sets by larger ones that represent submatrices with 7500 additional overlap. 7501 7502 Collective 7503 7504 Input Parameters: 7505 + mat - the matrix 7506 . n - the number of index sets 7507 . is - the array of index sets (these index sets will changed during the call) 7508 - ov - the additional overlap requested 7509 7510 Options Database Key: 7511 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7512 7513 Level: developer 7514 7515 Note: 7516 The computed overlap preserves the matrix block sizes when the blocks are square. 7517 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7518 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7519 7520 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7521 @*/ 7522 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7523 { 7524 PetscInt i, bs, cbs; 7525 7526 PetscFunctionBegin; 7527 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7528 PetscValidType(mat, 1); 7529 PetscValidLogicalCollectiveInt(mat, n, 2); 7530 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7531 if (n) { 7532 PetscAssertPointer(is, 3); 7533 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7534 } 7535 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7536 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7537 MatCheckPreallocated(mat, 1); 7538 7539 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7540 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7541 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7542 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7543 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7544 if (bs == cbs) { 7545 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7546 } 7547 PetscFunctionReturn(PETSC_SUCCESS); 7548 } 7549 7550 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7551 7552 /*@ 7553 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7554 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7555 additional overlap. 7556 7557 Collective 7558 7559 Input Parameters: 7560 + mat - the matrix 7561 . n - the number of index sets 7562 . is - the array of index sets (these index sets will changed during the call) 7563 - ov - the additional overlap requested 7564 7565 ` Options Database Key: 7566 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7567 7568 Level: developer 7569 7570 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7571 @*/ 7572 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7573 { 7574 PetscInt i; 7575 7576 PetscFunctionBegin; 7577 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7578 PetscValidType(mat, 1); 7579 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7580 if (n) { 7581 PetscAssertPointer(is, 3); 7582 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7583 } 7584 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7585 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7586 MatCheckPreallocated(mat, 1); 7587 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7588 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7589 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7590 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7591 PetscFunctionReturn(PETSC_SUCCESS); 7592 } 7593 7594 /*@ 7595 MatGetBlockSize - Returns the matrix block size. 7596 7597 Not Collective 7598 7599 Input Parameter: 7600 . mat - the matrix 7601 7602 Output Parameter: 7603 . bs - block size 7604 7605 Level: intermediate 7606 7607 Notes: 7608 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7609 7610 If the block size has not been set yet this routine returns 1. 7611 7612 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7613 @*/ 7614 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7615 { 7616 PetscFunctionBegin; 7617 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7618 PetscAssertPointer(bs, 2); 7619 *bs = PetscAbs(mat->rmap->bs); 7620 PetscFunctionReturn(PETSC_SUCCESS); 7621 } 7622 7623 /*@ 7624 MatGetBlockSizes - Returns the matrix block row and column sizes. 7625 7626 Not Collective 7627 7628 Input Parameter: 7629 . mat - the matrix 7630 7631 Output Parameters: 7632 + rbs - row block size 7633 - cbs - column block size 7634 7635 Level: intermediate 7636 7637 Notes: 7638 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7639 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7640 7641 If a block size has not been set yet this routine returns 1. 7642 7643 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7644 @*/ 7645 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7646 { 7647 PetscFunctionBegin; 7648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7649 if (rbs) PetscAssertPointer(rbs, 2); 7650 if (cbs) PetscAssertPointer(cbs, 3); 7651 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7652 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7653 PetscFunctionReturn(PETSC_SUCCESS); 7654 } 7655 7656 /*@ 7657 MatSetBlockSize - Sets the matrix block size. 7658 7659 Logically Collective 7660 7661 Input Parameters: 7662 + mat - the matrix 7663 - bs - block size 7664 7665 Level: intermediate 7666 7667 Notes: 7668 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7669 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7670 7671 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7672 is compatible with the matrix local sizes. 7673 7674 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7675 @*/ 7676 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7677 { 7678 PetscFunctionBegin; 7679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7680 PetscValidLogicalCollectiveInt(mat, bs, 2); 7681 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7682 PetscFunctionReturn(PETSC_SUCCESS); 7683 } 7684 7685 typedef struct { 7686 PetscInt n; 7687 IS *is; 7688 Mat *mat; 7689 PetscObjectState nonzerostate; 7690 Mat C; 7691 } EnvelopeData; 7692 7693 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7694 { 7695 EnvelopeData *edata = (EnvelopeData *)*ptr; 7696 7697 PetscFunctionBegin; 7698 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7699 PetscCall(PetscFree(edata->is)); 7700 PetscCall(PetscFree(edata)); 7701 PetscFunctionReturn(PETSC_SUCCESS); 7702 } 7703 7704 /*@ 7705 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7706 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7707 7708 Collective 7709 7710 Input Parameter: 7711 . mat - the matrix 7712 7713 Level: intermediate 7714 7715 Notes: 7716 There can be zeros within the blocks 7717 7718 The blocks can overlap between processes, including laying on more than two processes 7719 7720 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7721 @*/ 7722 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7723 { 7724 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7725 PetscInt *diag, *odiag, sc; 7726 VecScatter scatter; 7727 PetscScalar *seqv; 7728 const PetscScalar *parv; 7729 const PetscInt *ia, *ja; 7730 PetscBool set, flag, done; 7731 Mat AA = mat, A; 7732 MPI_Comm comm; 7733 PetscMPIInt rank, size, tag; 7734 MPI_Status status; 7735 PetscContainer container; 7736 EnvelopeData *edata; 7737 Vec seq, par; 7738 IS isglobal; 7739 7740 PetscFunctionBegin; 7741 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7742 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7743 if (!set || !flag) { 7744 /* TODO: only needs nonzero structure of transpose */ 7745 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7746 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7747 } 7748 PetscCall(MatAIJGetLocalMat(AA, &A)); 7749 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7750 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7751 7752 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7753 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7754 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7755 PetscCallMPI(MPI_Comm_size(comm, &size)); 7756 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7757 7758 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7759 7760 if (rank > 0) { 7761 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7762 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7763 } 7764 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7765 for (i = 0; i < n; i++) { 7766 env = PetscMax(env, ja[ia[i + 1] - 1]); 7767 II = rstart + i; 7768 if (env == II) { 7769 starts[lblocks] = tbs; 7770 sizes[lblocks++] = 1 + II - tbs; 7771 tbs = 1 + II; 7772 } 7773 } 7774 if (rank < size - 1) { 7775 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7776 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7777 } 7778 7779 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7780 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7781 PetscCall(MatDestroy(&A)); 7782 7783 PetscCall(PetscNew(&edata)); 7784 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7785 edata->n = lblocks; 7786 /* create IS needed for extracting blocks from the original matrix */ 7787 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7788 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7789 7790 /* Create the resulting inverse matrix structure with preallocation information */ 7791 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7792 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7793 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7794 PetscCall(MatSetType(edata->C, MATAIJ)); 7795 7796 /* Communicate the start and end of each row, from each block to the correct rank */ 7797 /* TODO: Use PetscSF instead of VecScatter */ 7798 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7799 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7800 PetscCall(VecGetArrayWrite(seq, &seqv)); 7801 for (PetscInt i = 0; i < lblocks; i++) { 7802 for (PetscInt j = 0; j < sizes[i]; j++) { 7803 seqv[cnt] = starts[i]; 7804 seqv[cnt + 1] = starts[i] + sizes[i]; 7805 cnt += 2; 7806 } 7807 } 7808 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7809 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7810 sc -= cnt; 7811 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7812 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7813 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7814 PetscCall(ISDestroy(&isglobal)); 7815 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7816 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7817 PetscCall(VecScatterDestroy(&scatter)); 7818 PetscCall(VecDestroy(&seq)); 7819 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7820 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7821 PetscCall(VecGetArrayRead(par, &parv)); 7822 cnt = 0; 7823 PetscCall(MatGetSize(mat, NULL, &n)); 7824 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7825 PetscInt start, end, d = 0, od = 0; 7826 7827 start = (PetscInt)PetscRealPart(parv[cnt]); 7828 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7829 cnt += 2; 7830 7831 if (start < cstart) { 7832 od += cstart - start + n - cend; 7833 d += cend - cstart; 7834 } else if (start < cend) { 7835 od += n - cend; 7836 d += cend - start; 7837 } else od += n - start; 7838 if (end <= cstart) { 7839 od -= cstart - end + n - cend; 7840 d -= cend - cstart; 7841 } else if (end < cend) { 7842 od -= n - cend; 7843 d -= cend - end; 7844 } else od -= n - end; 7845 7846 odiag[i] = od; 7847 diag[i] = d; 7848 } 7849 PetscCall(VecRestoreArrayRead(par, &parv)); 7850 PetscCall(VecDestroy(&par)); 7851 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7852 PetscCall(PetscFree2(diag, odiag)); 7853 PetscCall(PetscFree2(sizes, starts)); 7854 7855 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7856 PetscCall(PetscContainerSetPointer(container, edata)); 7857 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7858 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7859 PetscCall(PetscObjectDereference((PetscObject)container)); 7860 PetscFunctionReturn(PETSC_SUCCESS); 7861 } 7862 7863 /*@ 7864 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7865 7866 Collective 7867 7868 Input Parameters: 7869 + A - the matrix 7870 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7871 7872 Output Parameter: 7873 . C - matrix with inverted block diagonal of `A` 7874 7875 Level: advanced 7876 7877 Note: 7878 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7879 7880 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7881 @*/ 7882 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7883 { 7884 PetscContainer container; 7885 EnvelopeData *edata; 7886 PetscObjectState nonzerostate; 7887 7888 PetscFunctionBegin; 7889 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7890 if (!container) { 7891 PetscCall(MatComputeVariableBlockEnvelope(A)); 7892 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7893 } 7894 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7895 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7896 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7897 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7898 7899 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7900 *C = edata->C; 7901 7902 for (PetscInt i = 0; i < edata->n; i++) { 7903 Mat D; 7904 PetscScalar *dvalues; 7905 7906 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7907 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7908 PetscCall(MatSeqDenseInvert(D)); 7909 PetscCall(MatDenseGetArray(D, &dvalues)); 7910 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7911 PetscCall(MatDestroy(&D)); 7912 } 7913 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7914 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7915 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7916 PetscFunctionReturn(PETSC_SUCCESS); 7917 } 7918 7919 /*@ 7920 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7921 7922 Not Collective 7923 7924 Input Parameters: 7925 + mat - the matrix 7926 . nblocks - the number of blocks on this process, each block can only exist on a single process 7927 - bsizes - the block sizes 7928 7929 Level: intermediate 7930 7931 Notes: 7932 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7933 7934 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. 7935 7936 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7937 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7938 @*/ 7939 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7940 { 7941 PetscInt ncnt = 0, nlocal; 7942 7943 PetscFunctionBegin; 7944 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7945 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7946 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); 7947 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7948 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); 7949 PetscCall(PetscFree(mat->bsizes)); 7950 mat->nblocks = nblocks; 7951 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7952 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7953 PetscFunctionReturn(PETSC_SUCCESS); 7954 } 7955 7956 /*@C 7957 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7958 7959 Not Collective; No Fortran Support 7960 7961 Input Parameter: 7962 . mat - the matrix 7963 7964 Output Parameters: 7965 + nblocks - the number of blocks on this process 7966 - bsizes - the block sizes 7967 7968 Level: intermediate 7969 7970 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7971 @*/ 7972 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7973 { 7974 PetscFunctionBegin; 7975 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7976 if (nblocks) *nblocks = mat->nblocks; 7977 if (bsizes) *bsizes = mat->bsizes; 7978 PetscFunctionReturn(PETSC_SUCCESS); 7979 } 7980 7981 /*@ 7982 MatSetBlockSizes - Sets the matrix block row and column sizes. 7983 7984 Logically Collective 7985 7986 Input Parameters: 7987 + mat - the matrix 7988 . rbs - row block size 7989 - cbs - column block size 7990 7991 Level: intermediate 7992 7993 Notes: 7994 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7995 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7996 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7997 7998 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7999 are compatible with the matrix local sizes. 8000 8001 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 8002 8003 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 8004 @*/ 8005 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8006 { 8007 PetscFunctionBegin; 8008 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8009 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8010 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8011 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8012 if (mat->rmap->refcnt) { 8013 ISLocalToGlobalMapping l2g = NULL; 8014 PetscLayout nmap = NULL; 8015 8016 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8017 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8018 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8019 mat->rmap = nmap; 8020 mat->rmap->mapping = l2g; 8021 } 8022 if (mat->cmap->refcnt) { 8023 ISLocalToGlobalMapping l2g = NULL; 8024 PetscLayout nmap = NULL; 8025 8026 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8027 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8028 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8029 mat->cmap = nmap; 8030 mat->cmap->mapping = l2g; 8031 } 8032 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8033 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8034 PetscFunctionReturn(PETSC_SUCCESS); 8035 } 8036 8037 /*@ 8038 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8039 8040 Logically Collective 8041 8042 Input Parameters: 8043 + mat - the matrix 8044 . fromRow - matrix from which to copy row block size 8045 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8046 8047 Level: developer 8048 8049 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8050 @*/ 8051 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8052 { 8053 PetscFunctionBegin; 8054 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8055 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8056 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8057 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8058 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8059 PetscFunctionReturn(PETSC_SUCCESS); 8060 } 8061 8062 /*@ 8063 MatResidual - Default routine to calculate the residual r = b - Ax 8064 8065 Collective 8066 8067 Input Parameters: 8068 + mat - the matrix 8069 . b - the right-hand-side 8070 - x - the approximate solution 8071 8072 Output Parameter: 8073 . r - location to store the residual 8074 8075 Level: developer 8076 8077 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8078 @*/ 8079 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8080 { 8081 PetscFunctionBegin; 8082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8083 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8084 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8085 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8086 PetscValidType(mat, 1); 8087 MatCheckPreallocated(mat, 1); 8088 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8089 if (!mat->ops->residual) { 8090 PetscCall(MatMult(mat, x, r)); 8091 PetscCall(VecAYPX(r, -1.0, b)); 8092 } else { 8093 PetscUseTypeMethod(mat, residual, b, x, r); 8094 } 8095 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8096 PetscFunctionReturn(PETSC_SUCCESS); 8097 } 8098 8099 /*MC 8100 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8101 8102 Synopsis: 8103 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8104 8105 Not Collective 8106 8107 Input Parameters: 8108 + A - the matrix 8109 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8110 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8111 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8112 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8113 always used. 8114 8115 Output Parameters: 8116 + n - number of local rows in the (possibly compressed) matrix 8117 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8118 . ja - the column indices 8119 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8120 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8121 8122 Level: developer 8123 8124 Note: 8125 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8126 8127 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8128 M*/ 8129 8130 /*MC 8131 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8132 8133 Synopsis: 8134 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8135 8136 Not Collective 8137 8138 Input Parameters: 8139 + A - the matrix 8140 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8141 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8142 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8143 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8144 always used. 8145 . n - number of local rows in the (possibly compressed) matrix 8146 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8147 . ja - the column indices 8148 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8149 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8150 8151 Level: developer 8152 8153 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8154 M*/ 8155 8156 /*@C 8157 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8158 8159 Collective 8160 8161 Input Parameters: 8162 + mat - the matrix 8163 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8164 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8165 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8166 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8167 always used. 8168 8169 Output Parameters: 8170 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8171 . 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 8172 . ja - the column indices, use `NULL` if not needed 8173 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8174 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8175 8176 Level: developer 8177 8178 Notes: 8179 You CANNOT change any of the ia[] or ja[] values. 8180 8181 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8182 8183 Fortran Notes: 8184 Use 8185 .vb 8186 PetscInt, pointer :: ia(:),ja(:) 8187 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8188 ! Access the ith and jth entries via ia(i) and ja(j) 8189 .ve 8190 8191 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8192 8193 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8194 @*/ 8195 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8196 { 8197 PetscFunctionBegin; 8198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8199 PetscValidType(mat, 1); 8200 if (n) PetscAssertPointer(n, 5); 8201 if (ia) PetscAssertPointer(ia, 6); 8202 if (ja) PetscAssertPointer(ja, 7); 8203 if (done) PetscAssertPointer(done, 8); 8204 MatCheckPreallocated(mat, 1); 8205 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8206 else { 8207 if (done) *done = PETSC_TRUE; 8208 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8209 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8210 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8211 } 8212 PetscFunctionReturn(PETSC_SUCCESS); 8213 } 8214 8215 /*@C 8216 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8217 8218 Collective 8219 8220 Input Parameters: 8221 + mat - the matrix 8222 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8223 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8224 symmetrized 8225 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8226 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8227 always used. 8228 . n - number of columns in the (possibly compressed) matrix 8229 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8230 - ja - the row indices 8231 8232 Output Parameter: 8233 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8234 8235 Level: developer 8236 8237 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8238 @*/ 8239 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8240 { 8241 PetscFunctionBegin; 8242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8243 PetscValidType(mat, 1); 8244 PetscAssertPointer(n, 5); 8245 if (ia) PetscAssertPointer(ia, 6); 8246 if (ja) PetscAssertPointer(ja, 7); 8247 PetscAssertPointer(done, 8); 8248 MatCheckPreallocated(mat, 1); 8249 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8250 else { 8251 *done = PETSC_TRUE; 8252 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8253 } 8254 PetscFunctionReturn(PETSC_SUCCESS); 8255 } 8256 8257 /*@C 8258 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8259 8260 Collective 8261 8262 Input Parameters: 8263 + mat - the matrix 8264 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8265 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8266 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8267 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8268 always used. 8269 . n - size of (possibly compressed) matrix 8270 . ia - the row pointers 8271 - ja - the column indices 8272 8273 Output Parameter: 8274 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8275 8276 Level: developer 8277 8278 Note: 8279 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8280 us of the array after it has been restored. If you pass `NULL`, it will 8281 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8282 8283 Fortran Note: 8284 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8285 8286 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8287 @*/ 8288 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8289 { 8290 PetscFunctionBegin; 8291 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8292 PetscValidType(mat, 1); 8293 if (ia) PetscAssertPointer(ia, 6); 8294 if (ja) PetscAssertPointer(ja, 7); 8295 if (done) PetscAssertPointer(done, 8); 8296 MatCheckPreallocated(mat, 1); 8297 8298 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8299 else { 8300 if (done) *done = PETSC_TRUE; 8301 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8302 if (n) *n = 0; 8303 if (ia) *ia = NULL; 8304 if (ja) *ja = NULL; 8305 } 8306 PetscFunctionReturn(PETSC_SUCCESS); 8307 } 8308 8309 /*@C 8310 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8311 8312 Collective 8313 8314 Input Parameters: 8315 + mat - the matrix 8316 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8317 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8318 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8319 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8320 always used. 8321 8322 Output Parameters: 8323 + n - size of (possibly compressed) matrix 8324 . ia - the column pointers 8325 . ja - the row indices 8326 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8327 8328 Level: developer 8329 8330 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8331 @*/ 8332 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8333 { 8334 PetscFunctionBegin; 8335 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8336 PetscValidType(mat, 1); 8337 if (ia) PetscAssertPointer(ia, 6); 8338 if (ja) PetscAssertPointer(ja, 7); 8339 PetscAssertPointer(done, 8); 8340 MatCheckPreallocated(mat, 1); 8341 8342 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8343 else { 8344 *done = PETSC_TRUE; 8345 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8346 if (n) *n = 0; 8347 if (ia) *ia = NULL; 8348 if (ja) *ja = NULL; 8349 } 8350 PetscFunctionReturn(PETSC_SUCCESS); 8351 } 8352 8353 /*@ 8354 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8355 `MatGetColumnIJ()`. 8356 8357 Collective 8358 8359 Input Parameters: 8360 + mat - the matrix 8361 . ncolors - maximum color value 8362 . n - number of entries in colorarray 8363 - colorarray - array indicating color for each column 8364 8365 Output Parameter: 8366 . iscoloring - coloring generated using colorarray information 8367 8368 Level: developer 8369 8370 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8371 @*/ 8372 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8373 { 8374 PetscFunctionBegin; 8375 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8376 PetscValidType(mat, 1); 8377 PetscAssertPointer(colorarray, 4); 8378 PetscAssertPointer(iscoloring, 5); 8379 MatCheckPreallocated(mat, 1); 8380 8381 if (!mat->ops->coloringpatch) { 8382 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8383 } else { 8384 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8385 } 8386 PetscFunctionReturn(PETSC_SUCCESS); 8387 } 8388 8389 /*@ 8390 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8391 8392 Logically Collective 8393 8394 Input Parameter: 8395 . mat - the factored matrix to be reset 8396 8397 Level: developer 8398 8399 Notes: 8400 This routine should be used only with factored matrices formed by in-place 8401 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8402 format). This option can save memory, for example, when solving nonlinear 8403 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8404 ILU(0) preconditioner. 8405 8406 One can specify in-place ILU(0) factorization by calling 8407 .vb 8408 PCType(pc,PCILU); 8409 PCFactorSeUseInPlace(pc); 8410 .ve 8411 or by using the options -pc_type ilu -pc_factor_in_place 8412 8413 In-place factorization ILU(0) can also be used as a local 8414 solver for the blocks within the block Jacobi or additive Schwarz 8415 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8416 for details on setting local solver options. 8417 8418 Most users should employ the `KSP` interface for linear solvers 8419 instead of working directly with matrix algebra routines such as this. 8420 See, e.g., `KSPCreate()`. 8421 8422 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8423 @*/ 8424 PetscErrorCode MatSetUnfactored(Mat mat) 8425 { 8426 PetscFunctionBegin; 8427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8428 PetscValidType(mat, 1); 8429 MatCheckPreallocated(mat, 1); 8430 mat->factortype = MAT_FACTOR_NONE; 8431 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8432 PetscUseTypeMethod(mat, setunfactored); 8433 PetscFunctionReturn(PETSC_SUCCESS); 8434 } 8435 8436 /*MC 8437 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8438 8439 Synopsis: 8440 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8441 8442 Not Collective 8443 8444 Input Parameter: 8445 . x - matrix 8446 8447 Output Parameters: 8448 + xx_v - the Fortran pointer to the array 8449 - ierr - error code 8450 8451 Example of Usage: 8452 .vb 8453 PetscScalar, pointer xx_v(:,:) 8454 .... 8455 call MatDenseGetArrayF90(x,xx_v,ierr) 8456 a = xx_v(3) 8457 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8458 .ve 8459 8460 Level: advanced 8461 8462 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8463 M*/ 8464 8465 /*MC 8466 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8467 accessed with `MatDenseGetArrayF90()`. 8468 8469 Synopsis: 8470 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8471 8472 Not Collective 8473 8474 Input Parameters: 8475 + x - matrix 8476 - xx_v - the Fortran90 pointer to the array 8477 8478 Output Parameter: 8479 . ierr - error code 8480 8481 Example of Usage: 8482 .vb 8483 PetscScalar, pointer xx_v(:,:) 8484 .... 8485 call MatDenseGetArrayF90(x,xx_v,ierr) 8486 a = xx_v(3) 8487 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8488 .ve 8489 8490 Level: advanced 8491 8492 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8493 M*/ 8494 8495 /*MC 8496 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8497 8498 Synopsis: 8499 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8500 8501 Not Collective 8502 8503 Input Parameter: 8504 . x - matrix 8505 8506 Output Parameters: 8507 + xx_v - the Fortran pointer to the array 8508 - ierr - error code 8509 8510 Example of Usage: 8511 .vb 8512 PetscScalar, pointer xx_v(:) 8513 .... 8514 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8515 a = xx_v(3) 8516 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8517 .ve 8518 8519 Level: advanced 8520 8521 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8522 M*/ 8523 8524 /*MC 8525 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8526 accessed with `MatSeqAIJGetArrayF90()`. 8527 8528 Synopsis: 8529 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8530 8531 Not Collective 8532 8533 Input Parameters: 8534 + x - matrix 8535 - xx_v - the Fortran90 pointer to the array 8536 8537 Output Parameter: 8538 . ierr - error code 8539 8540 Example of Usage: 8541 .vb 8542 PetscScalar, pointer xx_v(:) 8543 .... 8544 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8545 a = xx_v(3) 8546 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8547 .ve 8548 8549 Level: advanced 8550 8551 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8552 M*/ 8553 8554 /*@ 8555 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8556 as the original matrix. 8557 8558 Collective 8559 8560 Input Parameters: 8561 + mat - the original matrix 8562 . isrow - parallel `IS` containing the rows this processor should obtain 8563 . 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. 8564 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8565 8566 Output Parameter: 8567 . newmat - the new submatrix, of the same type as the original matrix 8568 8569 Level: advanced 8570 8571 Notes: 8572 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8573 8574 Some matrix types place restrictions on the row and column indices, such 8575 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; 8576 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8577 8578 The index sets may not have duplicate entries. 8579 8580 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8581 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8582 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8583 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8584 you are finished using it. 8585 8586 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8587 the input matrix. 8588 8589 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8590 8591 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8592 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8593 8594 Example usage: 8595 Consider the following 8x8 matrix with 34 non-zero values, that is 8596 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8597 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8598 as follows 8599 .vb 8600 1 2 0 | 0 3 0 | 0 4 8601 Proc0 0 5 6 | 7 0 0 | 8 0 8602 9 0 10 | 11 0 0 | 12 0 8603 ------------------------------------- 8604 13 0 14 | 15 16 17 | 0 0 8605 Proc1 0 18 0 | 19 20 21 | 0 0 8606 0 0 0 | 22 23 0 | 24 0 8607 ------------------------------------- 8608 Proc2 25 26 27 | 0 0 28 | 29 0 8609 30 0 0 | 31 32 33 | 0 34 8610 .ve 8611 8612 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8613 8614 .vb 8615 2 0 | 0 3 0 | 0 8616 Proc0 5 6 | 7 0 0 | 8 8617 ------------------------------- 8618 Proc1 18 0 | 19 20 21 | 0 8619 ------------------------------- 8620 Proc2 26 27 | 0 0 28 | 29 8621 0 0 | 31 32 33 | 0 8622 .ve 8623 8624 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8625 @*/ 8626 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8627 { 8628 PetscMPIInt size; 8629 Mat *local; 8630 IS iscoltmp; 8631 PetscBool flg; 8632 8633 PetscFunctionBegin; 8634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8635 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8636 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8637 PetscAssertPointer(newmat, 5); 8638 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8639 PetscValidType(mat, 1); 8640 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8641 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8642 8643 MatCheckPreallocated(mat, 1); 8644 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8645 8646 if (!iscol || isrow == iscol) { 8647 PetscBool stride; 8648 PetscMPIInt grabentirematrix = 0, grab; 8649 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8650 if (stride) { 8651 PetscInt first, step, n, rstart, rend; 8652 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8653 if (step == 1) { 8654 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8655 if (rstart == first) { 8656 PetscCall(ISGetLocalSize(isrow, &n)); 8657 if (n == rend - rstart) grabentirematrix = 1; 8658 } 8659 } 8660 } 8661 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8662 if (grab) { 8663 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8664 if (cll == MAT_INITIAL_MATRIX) { 8665 *newmat = mat; 8666 PetscCall(PetscObjectReference((PetscObject)mat)); 8667 } 8668 PetscFunctionReturn(PETSC_SUCCESS); 8669 } 8670 } 8671 8672 if (!iscol) { 8673 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8674 } else { 8675 iscoltmp = iscol; 8676 } 8677 8678 /* if original matrix is on just one processor then use submatrix generated */ 8679 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8680 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8681 goto setproperties; 8682 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8683 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8684 *newmat = *local; 8685 PetscCall(PetscFree(local)); 8686 goto setproperties; 8687 } else if (!mat->ops->createsubmatrix) { 8688 /* Create a new matrix type that implements the operation using the full matrix */ 8689 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8690 switch (cll) { 8691 case MAT_INITIAL_MATRIX: 8692 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8693 break; 8694 case MAT_REUSE_MATRIX: 8695 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8696 break; 8697 default: 8698 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8699 } 8700 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8701 goto setproperties; 8702 } 8703 8704 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8705 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8706 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8707 8708 setproperties: 8709 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8710 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8711 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8712 } 8713 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8714 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8715 PetscFunctionReturn(PETSC_SUCCESS); 8716 } 8717 8718 /*@ 8719 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8720 8721 Not Collective 8722 8723 Input Parameters: 8724 + A - the matrix we wish to propagate options from 8725 - B - the matrix we wish to propagate options to 8726 8727 Level: beginner 8728 8729 Note: 8730 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8731 8732 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8733 @*/ 8734 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8735 { 8736 PetscFunctionBegin; 8737 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8738 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8739 B->symmetry_eternal = A->symmetry_eternal; 8740 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8741 B->symmetric = A->symmetric; 8742 B->structurally_symmetric = A->structurally_symmetric; 8743 B->spd = A->spd; 8744 B->hermitian = A->hermitian; 8745 PetscFunctionReturn(PETSC_SUCCESS); 8746 } 8747 8748 /*@ 8749 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8750 used during the assembly process to store values that belong to 8751 other processors. 8752 8753 Not Collective 8754 8755 Input Parameters: 8756 + mat - the matrix 8757 . size - the initial size of the stash. 8758 - bsize - the initial size of the block-stash(if used). 8759 8760 Options Database Keys: 8761 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8762 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8763 8764 Level: intermediate 8765 8766 Notes: 8767 The block-stash is used for values set with `MatSetValuesBlocked()` while 8768 the stash is used for values set with `MatSetValues()` 8769 8770 Run with the option -info and look for output of the form 8771 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8772 to determine the appropriate value, MM, to use for size and 8773 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8774 to determine the value, BMM to use for bsize 8775 8776 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8777 @*/ 8778 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8779 { 8780 PetscFunctionBegin; 8781 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8782 PetscValidType(mat, 1); 8783 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8784 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8785 PetscFunctionReturn(PETSC_SUCCESS); 8786 } 8787 8788 /*@ 8789 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8790 the matrix 8791 8792 Neighbor-wise Collective 8793 8794 Input Parameters: 8795 + A - the matrix 8796 . x - the vector to be multiplied by the interpolation operator 8797 - y - the vector to be added to the result 8798 8799 Output Parameter: 8800 . w - the resulting vector 8801 8802 Level: intermediate 8803 8804 Notes: 8805 `w` may be the same vector as `y`. 8806 8807 This allows one to use either the restriction or interpolation (its transpose) 8808 matrix to do the interpolation 8809 8810 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8811 @*/ 8812 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8813 { 8814 PetscInt M, N, Ny; 8815 8816 PetscFunctionBegin; 8817 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8818 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8819 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8820 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8821 PetscCall(MatGetSize(A, &M, &N)); 8822 PetscCall(VecGetSize(y, &Ny)); 8823 if (M == Ny) { 8824 PetscCall(MatMultAdd(A, x, y, w)); 8825 } else { 8826 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8827 } 8828 PetscFunctionReturn(PETSC_SUCCESS); 8829 } 8830 8831 /*@ 8832 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8833 the matrix 8834 8835 Neighbor-wise Collective 8836 8837 Input Parameters: 8838 + A - the matrix 8839 - x - the vector to be interpolated 8840 8841 Output Parameter: 8842 . y - the resulting vector 8843 8844 Level: intermediate 8845 8846 Note: 8847 This allows one to use either the restriction or interpolation (its transpose) 8848 matrix to do the interpolation 8849 8850 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8851 @*/ 8852 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8853 { 8854 PetscInt M, N, Ny; 8855 8856 PetscFunctionBegin; 8857 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8858 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8859 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8860 PetscCall(MatGetSize(A, &M, &N)); 8861 PetscCall(VecGetSize(y, &Ny)); 8862 if (M == Ny) { 8863 PetscCall(MatMult(A, x, y)); 8864 } else { 8865 PetscCall(MatMultTranspose(A, x, y)); 8866 } 8867 PetscFunctionReturn(PETSC_SUCCESS); 8868 } 8869 8870 /*@ 8871 MatRestrict - $y = A*x$ or $A^T*x$ 8872 8873 Neighbor-wise Collective 8874 8875 Input Parameters: 8876 + A - the matrix 8877 - x - the vector to be restricted 8878 8879 Output Parameter: 8880 . y - the resulting vector 8881 8882 Level: intermediate 8883 8884 Note: 8885 This allows one to use either the restriction or interpolation (its transpose) 8886 matrix to do the restriction 8887 8888 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8889 @*/ 8890 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8891 { 8892 PetscInt M, N, Nx; 8893 8894 PetscFunctionBegin; 8895 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8896 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8897 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8898 PetscCall(MatGetSize(A, &M, &N)); 8899 PetscCall(VecGetSize(x, &Nx)); 8900 if (M == Nx) { 8901 PetscCall(MatMultTranspose(A, x, y)); 8902 } else { 8903 PetscCall(MatMult(A, x, y)); 8904 } 8905 PetscFunctionReturn(PETSC_SUCCESS); 8906 } 8907 8908 /*@ 8909 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8910 8911 Neighbor-wise Collective 8912 8913 Input Parameters: 8914 + A - the matrix 8915 . x - the input dense matrix to be multiplied 8916 - w - the input dense matrix to be added to the result 8917 8918 Output Parameter: 8919 . y - the output dense matrix 8920 8921 Level: intermediate 8922 8923 Note: 8924 This allows one to use either the restriction or interpolation (its transpose) 8925 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8926 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8927 8928 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8929 @*/ 8930 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8931 { 8932 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8933 PetscBool trans = PETSC_TRUE; 8934 MatReuse reuse = MAT_INITIAL_MATRIX; 8935 8936 PetscFunctionBegin; 8937 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8938 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8939 PetscValidType(x, 2); 8940 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8941 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8942 PetscCall(MatGetSize(A, &M, &N)); 8943 PetscCall(MatGetSize(x, &Mx, &Nx)); 8944 if (N == Mx) trans = PETSC_FALSE; 8945 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); 8946 Mo = trans ? N : M; 8947 if (*y) { 8948 PetscCall(MatGetSize(*y, &My, &Ny)); 8949 if (Mo == My && Nx == Ny) { 8950 reuse = MAT_REUSE_MATRIX; 8951 } else { 8952 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); 8953 PetscCall(MatDestroy(y)); 8954 } 8955 } 8956 8957 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8958 PetscBool flg; 8959 8960 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8961 if (w) { 8962 PetscInt My, Ny, Mw, Nw; 8963 8964 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8965 PetscCall(MatGetSize(*y, &My, &Ny)); 8966 PetscCall(MatGetSize(w, &Mw, &Nw)); 8967 if (!flg || My != Mw || Ny != Nw) w = NULL; 8968 } 8969 if (!w) { 8970 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8971 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8972 PetscCall(PetscObjectDereference((PetscObject)w)); 8973 } else { 8974 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8975 } 8976 } 8977 if (!trans) { 8978 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8979 } else { 8980 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8981 } 8982 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8983 PetscFunctionReturn(PETSC_SUCCESS); 8984 } 8985 8986 /*@ 8987 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8988 8989 Neighbor-wise Collective 8990 8991 Input Parameters: 8992 + A - the matrix 8993 - x - the input dense matrix 8994 8995 Output Parameter: 8996 . y - the output dense matrix 8997 8998 Level: intermediate 8999 9000 Note: 9001 This allows one to use either the restriction or interpolation (its transpose) 9002 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 9003 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 9004 9005 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 9006 @*/ 9007 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 9008 { 9009 PetscFunctionBegin; 9010 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9011 PetscFunctionReturn(PETSC_SUCCESS); 9012 } 9013 9014 /*@ 9015 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 9016 9017 Neighbor-wise Collective 9018 9019 Input Parameters: 9020 + A - the matrix 9021 - x - the input dense matrix 9022 9023 Output Parameter: 9024 . y - the output dense matrix 9025 9026 Level: intermediate 9027 9028 Note: 9029 This allows one to use either the restriction or interpolation (its transpose) 9030 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 9031 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 9032 9033 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 9034 @*/ 9035 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 9036 { 9037 PetscFunctionBegin; 9038 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9039 PetscFunctionReturn(PETSC_SUCCESS); 9040 } 9041 9042 /*@ 9043 MatGetNullSpace - retrieves the null space of a matrix. 9044 9045 Logically Collective 9046 9047 Input Parameters: 9048 + mat - the matrix 9049 - nullsp - the null space object 9050 9051 Level: developer 9052 9053 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 9054 @*/ 9055 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 9056 { 9057 PetscFunctionBegin; 9058 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9059 PetscAssertPointer(nullsp, 2); 9060 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 9061 PetscFunctionReturn(PETSC_SUCCESS); 9062 } 9063 9064 /*@C 9065 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9066 9067 Logically Collective 9068 9069 Input Parameters: 9070 + n - the number of matrices 9071 - mat - the array of matrices 9072 9073 Output Parameters: 9074 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9075 9076 Level: developer 9077 9078 Note: 9079 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9080 9081 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9082 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9083 @*/ 9084 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9085 { 9086 PetscFunctionBegin; 9087 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9088 PetscAssertPointer(mat, 2); 9089 PetscAssertPointer(nullsp, 3); 9090 9091 PetscCall(PetscCalloc1(3 * n, nullsp)); 9092 for (PetscInt i = 0; i < n; i++) { 9093 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9094 (*nullsp)[i] = mat[i]->nullsp; 9095 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9096 (*nullsp)[n + i] = mat[i]->nearnullsp; 9097 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9098 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9099 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9100 } 9101 PetscFunctionReturn(PETSC_SUCCESS); 9102 } 9103 9104 /*@C 9105 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9106 9107 Logically Collective 9108 9109 Input Parameters: 9110 + n - the number of matrices 9111 . mat - the array of matrices 9112 - nullsp - an array of null spaces 9113 9114 Level: developer 9115 9116 Note: 9117 Call `MatGetNullSpaces()` to create `nullsp` 9118 9119 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9120 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9121 @*/ 9122 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9123 { 9124 PetscFunctionBegin; 9125 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9126 PetscAssertPointer(mat, 2); 9127 PetscAssertPointer(nullsp, 3); 9128 PetscAssertPointer(*nullsp, 3); 9129 9130 for (PetscInt i = 0; i < n; i++) { 9131 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9132 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9133 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9134 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9135 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9136 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9137 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9138 } 9139 PetscCall(PetscFree(*nullsp)); 9140 PetscFunctionReturn(PETSC_SUCCESS); 9141 } 9142 9143 /*@ 9144 MatSetNullSpace - attaches a null space to a matrix. 9145 9146 Logically Collective 9147 9148 Input Parameters: 9149 + mat - the matrix 9150 - nullsp - the null space object 9151 9152 Level: advanced 9153 9154 Notes: 9155 This null space is used by the `KSP` linear solvers to solve singular systems. 9156 9157 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` 9158 9159 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 9160 to zero but the linear system will still be solved in a least squares sense. 9161 9162 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9163 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)$. 9164 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 9165 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 9166 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$). 9167 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9168 9169 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9170 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9171 routine also automatically calls `MatSetTransposeNullSpace()`. 9172 9173 The user should call `MatNullSpaceDestroy()`. 9174 9175 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9176 `KSPSetPCSide()` 9177 @*/ 9178 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9179 { 9180 PetscFunctionBegin; 9181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9182 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9183 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9184 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9185 mat->nullsp = nullsp; 9186 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9187 PetscFunctionReturn(PETSC_SUCCESS); 9188 } 9189 9190 /*@ 9191 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9192 9193 Logically Collective 9194 9195 Input Parameters: 9196 + mat - the matrix 9197 - nullsp - the null space object 9198 9199 Level: developer 9200 9201 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9202 @*/ 9203 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9204 { 9205 PetscFunctionBegin; 9206 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9207 PetscValidType(mat, 1); 9208 PetscAssertPointer(nullsp, 2); 9209 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9210 PetscFunctionReturn(PETSC_SUCCESS); 9211 } 9212 9213 /*@ 9214 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9215 9216 Logically Collective 9217 9218 Input Parameters: 9219 + mat - the matrix 9220 - nullsp - the null space object 9221 9222 Level: advanced 9223 9224 Notes: 9225 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9226 9227 See `MatSetNullSpace()` 9228 9229 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9230 @*/ 9231 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9232 { 9233 PetscFunctionBegin; 9234 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9235 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9236 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9237 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9238 mat->transnullsp = nullsp; 9239 PetscFunctionReturn(PETSC_SUCCESS); 9240 } 9241 9242 /*@ 9243 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9244 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9245 9246 Logically Collective 9247 9248 Input Parameters: 9249 + mat - the matrix 9250 - nullsp - the null space object 9251 9252 Level: advanced 9253 9254 Notes: 9255 Overwrites any previous near null space that may have been attached 9256 9257 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9258 9259 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9260 @*/ 9261 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9262 { 9263 PetscFunctionBegin; 9264 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9265 PetscValidType(mat, 1); 9266 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9267 MatCheckPreallocated(mat, 1); 9268 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9269 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9270 mat->nearnullsp = nullsp; 9271 PetscFunctionReturn(PETSC_SUCCESS); 9272 } 9273 9274 /*@ 9275 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9276 9277 Not Collective 9278 9279 Input Parameter: 9280 . mat - the matrix 9281 9282 Output Parameter: 9283 . nullsp - the null space object, `NULL` if not set 9284 9285 Level: advanced 9286 9287 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9288 @*/ 9289 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9290 { 9291 PetscFunctionBegin; 9292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9293 PetscValidType(mat, 1); 9294 PetscAssertPointer(nullsp, 2); 9295 MatCheckPreallocated(mat, 1); 9296 *nullsp = mat->nearnullsp; 9297 PetscFunctionReturn(PETSC_SUCCESS); 9298 } 9299 9300 /*@ 9301 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9302 9303 Collective 9304 9305 Input Parameters: 9306 + mat - the matrix 9307 . row - row/column permutation 9308 - info - information on desired factorization process 9309 9310 Level: developer 9311 9312 Notes: 9313 Probably really in-place only when level of fill is zero, otherwise allocates 9314 new space to store factored matrix and deletes previous memory. 9315 9316 Most users should employ the `KSP` interface for linear solvers 9317 instead of working directly with matrix algebra routines such as this. 9318 See, e.g., `KSPCreate()`. 9319 9320 Developer Note: 9321 The Fortran interface is not autogenerated as the 9322 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9323 9324 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9325 @*/ 9326 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9327 { 9328 PetscFunctionBegin; 9329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9330 PetscValidType(mat, 1); 9331 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9332 PetscAssertPointer(info, 3); 9333 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9334 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9335 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9336 MatCheckPreallocated(mat, 1); 9337 PetscUseTypeMethod(mat, iccfactor, row, info); 9338 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9339 PetscFunctionReturn(PETSC_SUCCESS); 9340 } 9341 9342 /*@ 9343 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9344 ghosted ones. 9345 9346 Not Collective 9347 9348 Input Parameters: 9349 + mat - the matrix 9350 - diag - the diagonal values, including ghost ones 9351 9352 Level: developer 9353 9354 Notes: 9355 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9356 9357 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9358 9359 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9360 @*/ 9361 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9362 { 9363 PetscMPIInt size; 9364 9365 PetscFunctionBegin; 9366 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9367 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9368 PetscValidType(mat, 1); 9369 9370 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9371 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9372 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9373 if (size == 1) { 9374 PetscInt n, m; 9375 PetscCall(VecGetSize(diag, &n)); 9376 PetscCall(MatGetSize(mat, NULL, &m)); 9377 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9378 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9379 } else { 9380 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9381 } 9382 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9383 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9384 PetscFunctionReturn(PETSC_SUCCESS); 9385 } 9386 9387 /*@ 9388 MatGetInertia - Gets the inertia from a factored matrix 9389 9390 Collective 9391 9392 Input Parameter: 9393 . mat - the matrix 9394 9395 Output Parameters: 9396 + nneg - number of negative eigenvalues 9397 . nzero - number of zero eigenvalues 9398 - npos - number of positive eigenvalues 9399 9400 Level: advanced 9401 9402 Note: 9403 Matrix must have been factored by `MatCholeskyFactor()` 9404 9405 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9406 @*/ 9407 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9408 { 9409 PetscFunctionBegin; 9410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9411 PetscValidType(mat, 1); 9412 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9413 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9414 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9415 PetscFunctionReturn(PETSC_SUCCESS); 9416 } 9417 9418 /*@C 9419 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9420 9421 Neighbor-wise Collective 9422 9423 Input Parameters: 9424 + mat - the factored matrix obtained with `MatGetFactor()` 9425 - b - the right-hand-side vectors 9426 9427 Output Parameter: 9428 . x - the result vectors 9429 9430 Level: developer 9431 9432 Note: 9433 The vectors `b` and `x` cannot be the same. I.e., one cannot 9434 call `MatSolves`(A,x,x). 9435 9436 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9437 @*/ 9438 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9439 { 9440 PetscFunctionBegin; 9441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9442 PetscValidType(mat, 1); 9443 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9444 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9445 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9446 9447 MatCheckPreallocated(mat, 1); 9448 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9449 PetscUseTypeMethod(mat, solves, b, x); 9450 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9451 PetscFunctionReturn(PETSC_SUCCESS); 9452 } 9453 9454 /*@ 9455 MatIsSymmetric - Test whether a matrix is symmetric 9456 9457 Collective 9458 9459 Input Parameters: 9460 + A - the matrix to test 9461 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9462 9463 Output Parameter: 9464 . flg - the result 9465 9466 Level: intermediate 9467 9468 Notes: 9469 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9470 9471 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9472 9473 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9474 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9475 9476 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9477 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9478 @*/ 9479 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9480 { 9481 PetscFunctionBegin; 9482 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9483 PetscAssertPointer(flg, 3); 9484 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9485 else { 9486 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9487 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9488 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9489 } 9490 PetscFunctionReturn(PETSC_SUCCESS); 9491 } 9492 9493 /*@ 9494 MatIsHermitian - Test whether a matrix is Hermitian 9495 9496 Collective 9497 9498 Input Parameters: 9499 + A - the matrix to test 9500 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9501 9502 Output Parameter: 9503 . flg - the result 9504 9505 Level: intermediate 9506 9507 Notes: 9508 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9509 9510 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9511 9512 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9513 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9514 9515 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9516 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9517 @*/ 9518 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9519 { 9520 PetscFunctionBegin; 9521 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9522 PetscAssertPointer(flg, 3); 9523 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9524 else { 9525 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9526 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9527 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9528 } 9529 PetscFunctionReturn(PETSC_SUCCESS); 9530 } 9531 9532 /*@ 9533 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9534 9535 Not Collective 9536 9537 Input Parameter: 9538 . A - the matrix to check 9539 9540 Output Parameters: 9541 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9542 - flg - the result (only valid if set is `PETSC_TRUE`) 9543 9544 Level: advanced 9545 9546 Notes: 9547 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9548 if you want it explicitly checked 9549 9550 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9551 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9552 9553 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9554 @*/ 9555 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9556 { 9557 PetscFunctionBegin; 9558 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9559 PetscAssertPointer(set, 2); 9560 PetscAssertPointer(flg, 3); 9561 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9562 *set = PETSC_TRUE; 9563 *flg = PetscBool3ToBool(A->symmetric); 9564 } else { 9565 *set = PETSC_FALSE; 9566 } 9567 PetscFunctionReturn(PETSC_SUCCESS); 9568 } 9569 9570 /*@ 9571 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9572 9573 Not Collective 9574 9575 Input Parameter: 9576 . A - the matrix to check 9577 9578 Output Parameters: 9579 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9580 - flg - the result (only valid if set is `PETSC_TRUE`) 9581 9582 Level: advanced 9583 9584 Notes: 9585 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9586 9587 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9588 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9589 9590 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9591 @*/ 9592 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9593 { 9594 PetscFunctionBegin; 9595 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9596 PetscAssertPointer(set, 2); 9597 PetscAssertPointer(flg, 3); 9598 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9599 *set = PETSC_TRUE; 9600 *flg = PetscBool3ToBool(A->spd); 9601 } else { 9602 *set = PETSC_FALSE; 9603 } 9604 PetscFunctionReturn(PETSC_SUCCESS); 9605 } 9606 9607 /*@ 9608 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9609 9610 Not Collective 9611 9612 Input Parameter: 9613 . A - the matrix to check 9614 9615 Output Parameters: 9616 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9617 - flg - the result (only valid if set is `PETSC_TRUE`) 9618 9619 Level: advanced 9620 9621 Notes: 9622 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9623 if you want it explicitly checked 9624 9625 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9626 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9627 9628 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9629 @*/ 9630 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9631 { 9632 PetscFunctionBegin; 9633 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9634 PetscAssertPointer(set, 2); 9635 PetscAssertPointer(flg, 3); 9636 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9637 *set = PETSC_TRUE; 9638 *flg = PetscBool3ToBool(A->hermitian); 9639 } else { 9640 *set = PETSC_FALSE; 9641 } 9642 PetscFunctionReturn(PETSC_SUCCESS); 9643 } 9644 9645 /*@ 9646 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9647 9648 Collective 9649 9650 Input Parameter: 9651 . A - the matrix to test 9652 9653 Output Parameter: 9654 . flg - the result 9655 9656 Level: intermediate 9657 9658 Notes: 9659 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9660 9661 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 9662 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9663 9664 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9665 @*/ 9666 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9667 { 9668 PetscFunctionBegin; 9669 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9670 PetscAssertPointer(flg, 2); 9671 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9672 *flg = PetscBool3ToBool(A->structurally_symmetric); 9673 } else { 9674 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9675 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9676 } 9677 PetscFunctionReturn(PETSC_SUCCESS); 9678 } 9679 9680 /*@ 9681 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9682 9683 Not Collective 9684 9685 Input Parameter: 9686 . A - the matrix to check 9687 9688 Output Parameters: 9689 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9690 - flg - the result (only valid if set is PETSC_TRUE) 9691 9692 Level: advanced 9693 9694 Notes: 9695 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 9696 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9697 9698 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9699 9700 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9701 @*/ 9702 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9703 { 9704 PetscFunctionBegin; 9705 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9706 PetscAssertPointer(set, 2); 9707 PetscAssertPointer(flg, 3); 9708 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9709 *set = PETSC_TRUE; 9710 *flg = PetscBool3ToBool(A->structurally_symmetric); 9711 } else { 9712 *set = PETSC_FALSE; 9713 } 9714 PetscFunctionReturn(PETSC_SUCCESS); 9715 } 9716 9717 /*@ 9718 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9719 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9720 9721 Not Collective 9722 9723 Input Parameter: 9724 . mat - the matrix 9725 9726 Output Parameters: 9727 + nstash - the size of the stash 9728 . reallocs - the number of additional mallocs incurred. 9729 . bnstash - the size of the block stash 9730 - breallocs - the number of additional mallocs incurred.in the block stash 9731 9732 Level: advanced 9733 9734 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9735 @*/ 9736 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9737 { 9738 PetscFunctionBegin; 9739 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9740 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9741 PetscFunctionReturn(PETSC_SUCCESS); 9742 } 9743 9744 /*@ 9745 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9746 parallel layout, `PetscLayout` for rows and columns 9747 9748 Collective 9749 9750 Input Parameter: 9751 . mat - the matrix 9752 9753 Output Parameters: 9754 + right - (optional) vector that the matrix can be multiplied against 9755 - left - (optional) vector that the matrix vector product can be stored in 9756 9757 Level: advanced 9758 9759 Notes: 9760 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()`. 9761 9762 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9763 9764 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9765 @*/ 9766 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9767 { 9768 PetscFunctionBegin; 9769 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9770 PetscValidType(mat, 1); 9771 if (mat->ops->getvecs) { 9772 PetscUseTypeMethod(mat, getvecs, right, left); 9773 } else { 9774 if (right) { 9775 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9776 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9777 PetscCall(VecSetType(*right, mat->defaultvectype)); 9778 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9779 if (mat->boundtocpu && mat->bindingpropagates) { 9780 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9781 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9782 } 9783 #endif 9784 } 9785 if (left) { 9786 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9787 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9788 PetscCall(VecSetType(*left, mat->defaultvectype)); 9789 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9790 if (mat->boundtocpu && mat->bindingpropagates) { 9791 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9792 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9793 } 9794 #endif 9795 } 9796 } 9797 PetscFunctionReturn(PETSC_SUCCESS); 9798 } 9799 9800 /*@ 9801 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9802 with default values. 9803 9804 Not Collective 9805 9806 Input Parameter: 9807 . info - the `MatFactorInfo` data structure 9808 9809 Level: developer 9810 9811 Notes: 9812 The solvers are generally used through the `KSP` and `PC` objects, for example 9813 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9814 9815 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9816 9817 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9818 @*/ 9819 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9820 { 9821 PetscFunctionBegin; 9822 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9823 PetscFunctionReturn(PETSC_SUCCESS); 9824 } 9825 9826 /*@ 9827 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9828 9829 Collective 9830 9831 Input Parameters: 9832 + mat - the factored matrix 9833 - is - the index set defining the Schur indices (0-based) 9834 9835 Level: advanced 9836 9837 Notes: 9838 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9839 9840 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9841 9842 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9843 9844 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9845 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9846 @*/ 9847 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9848 { 9849 PetscErrorCode (*f)(Mat, IS); 9850 9851 PetscFunctionBegin; 9852 PetscValidType(mat, 1); 9853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9854 PetscValidType(is, 2); 9855 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9856 PetscCheckSameComm(mat, 1, is, 2); 9857 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9858 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9859 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9860 PetscCall(MatDestroy(&mat->schur)); 9861 PetscCall((*f)(mat, is)); 9862 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9863 PetscFunctionReturn(PETSC_SUCCESS); 9864 } 9865 9866 /*@ 9867 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9868 9869 Logically Collective 9870 9871 Input Parameters: 9872 + F - the factored matrix obtained by calling `MatGetFactor()` 9873 . S - location where to return the Schur complement, can be `NULL` 9874 - status - the status of the Schur complement matrix, can be `NULL` 9875 9876 Level: advanced 9877 9878 Notes: 9879 You must call `MatFactorSetSchurIS()` before calling this routine. 9880 9881 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9882 9883 The routine provides a copy of the Schur matrix stored within the solver data structures. 9884 The caller must destroy the object when it is no longer needed. 9885 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9886 9887 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) 9888 9889 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9890 9891 Developer Note: 9892 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9893 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9894 9895 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9896 @*/ 9897 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9898 { 9899 PetscFunctionBegin; 9900 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9901 if (S) PetscAssertPointer(S, 2); 9902 if (status) PetscAssertPointer(status, 3); 9903 if (S) { 9904 PetscErrorCode (*f)(Mat, Mat *); 9905 9906 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9907 if (f) { 9908 PetscCall((*f)(F, S)); 9909 } else { 9910 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9911 } 9912 } 9913 if (status) *status = F->schur_status; 9914 PetscFunctionReturn(PETSC_SUCCESS); 9915 } 9916 9917 /*@ 9918 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9919 9920 Logically Collective 9921 9922 Input Parameters: 9923 + F - the factored matrix obtained by calling `MatGetFactor()` 9924 . S - location where to return the Schur complement, can be `NULL` 9925 - status - the status of the Schur complement matrix, can be `NULL` 9926 9927 Level: advanced 9928 9929 Notes: 9930 You must call `MatFactorSetSchurIS()` before calling this routine. 9931 9932 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9933 9934 The routine returns a the Schur Complement stored within the data structures of the solver. 9935 9936 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9937 9938 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9939 9940 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9941 9942 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9943 9944 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9945 @*/ 9946 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9947 { 9948 PetscFunctionBegin; 9949 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9950 if (S) { 9951 PetscAssertPointer(S, 2); 9952 *S = F->schur; 9953 } 9954 if (status) { 9955 PetscAssertPointer(status, 3); 9956 *status = F->schur_status; 9957 } 9958 PetscFunctionReturn(PETSC_SUCCESS); 9959 } 9960 9961 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9962 { 9963 Mat S = F->schur; 9964 9965 PetscFunctionBegin; 9966 switch (F->schur_status) { 9967 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9968 case MAT_FACTOR_SCHUR_INVERTED: 9969 if (S) { 9970 S->ops->solve = NULL; 9971 S->ops->matsolve = NULL; 9972 S->ops->solvetranspose = NULL; 9973 S->ops->matsolvetranspose = NULL; 9974 S->ops->solveadd = NULL; 9975 S->ops->solvetransposeadd = NULL; 9976 S->factortype = MAT_FACTOR_NONE; 9977 PetscCall(PetscFree(S->solvertype)); 9978 } 9979 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9980 break; 9981 default: 9982 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9983 } 9984 PetscFunctionReturn(PETSC_SUCCESS); 9985 } 9986 9987 /*@ 9988 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9989 9990 Logically Collective 9991 9992 Input Parameters: 9993 + F - the factored matrix obtained by calling `MatGetFactor()` 9994 . S - location where the Schur complement is stored 9995 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9996 9997 Level: advanced 9998 9999 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 10000 @*/ 10001 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 10002 { 10003 PetscFunctionBegin; 10004 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10005 if (S) { 10006 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 10007 *S = NULL; 10008 } 10009 F->schur_status = status; 10010 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 10011 PetscFunctionReturn(PETSC_SUCCESS); 10012 } 10013 10014 /*@ 10015 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 10016 10017 Logically Collective 10018 10019 Input Parameters: 10020 + F - the factored matrix obtained by calling `MatGetFactor()` 10021 . rhs - location where the right-hand side of the Schur complement system is stored 10022 - sol - location where the solution of the Schur complement system has to be returned 10023 10024 Level: advanced 10025 10026 Notes: 10027 The sizes of the vectors should match the size of the Schur complement 10028 10029 Must be called after `MatFactorSetSchurIS()` 10030 10031 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 10032 @*/ 10033 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 10034 { 10035 PetscFunctionBegin; 10036 PetscValidType(F, 1); 10037 PetscValidType(rhs, 2); 10038 PetscValidType(sol, 3); 10039 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10040 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10041 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10042 PetscCheckSameComm(F, 1, rhs, 2); 10043 PetscCheckSameComm(F, 1, sol, 3); 10044 PetscCall(MatFactorFactorizeSchurComplement(F)); 10045 switch (F->schur_status) { 10046 case MAT_FACTOR_SCHUR_FACTORED: 10047 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 10048 break; 10049 case MAT_FACTOR_SCHUR_INVERTED: 10050 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 10051 break; 10052 default: 10053 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10054 } 10055 PetscFunctionReturn(PETSC_SUCCESS); 10056 } 10057 10058 /*@ 10059 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 10060 10061 Logically Collective 10062 10063 Input Parameters: 10064 + F - the factored matrix obtained by calling `MatGetFactor()` 10065 . rhs - location where the right-hand side of the Schur complement system is stored 10066 - sol - location where the solution of the Schur complement system has to be returned 10067 10068 Level: advanced 10069 10070 Notes: 10071 The sizes of the vectors should match the size of the Schur complement 10072 10073 Must be called after `MatFactorSetSchurIS()` 10074 10075 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10076 @*/ 10077 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10078 { 10079 PetscFunctionBegin; 10080 PetscValidType(F, 1); 10081 PetscValidType(rhs, 2); 10082 PetscValidType(sol, 3); 10083 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10084 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10085 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10086 PetscCheckSameComm(F, 1, rhs, 2); 10087 PetscCheckSameComm(F, 1, sol, 3); 10088 PetscCall(MatFactorFactorizeSchurComplement(F)); 10089 switch (F->schur_status) { 10090 case MAT_FACTOR_SCHUR_FACTORED: 10091 PetscCall(MatSolve(F->schur, rhs, sol)); 10092 break; 10093 case MAT_FACTOR_SCHUR_INVERTED: 10094 PetscCall(MatMult(F->schur, rhs, sol)); 10095 break; 10096 default: 10097 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10098 } 10099 PetscFunctionReturn(PETSC_SUCCESS); 10100 } 10101 10102 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10103 #if PetscDefined(HAVE_CUDA) 10104 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10105 #endif 10106 10107 /* Schur status updated in the interface */ 10108 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10109 { 10110 Mat S = F->schur; 10111 10112 PetscFunctionBegin; 10113 if (S) { 10114 PetscMPIInt size; 10115 PetscBool isdense, isdensecuda; 10116 10117 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10118 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10119 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10120 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10121 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10122 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10123 if (isdense) { 10124 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10125 } else if (isdensecuda) { 10126 #if defined(PETSC_HAVE_CUDA) 10127 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10128 #endif 10129 } 10130 // HIP?????????????? 10131 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10132 } 10133 PetscFunctionReturn(PETSC_SUCCESS); 10134 } 10135 10136 /*@ 10137 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10138 10139 Logically Collective 10140 10141 Input Parameter: 10142 . F - the factored matrix obtained by calling `MatGetFactor()` 10143 10144 Level: advanced 10145 10146 Notes: 10147 Must be called after `MatFactorSetSchurIS()`. 10148 10149 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10150 10151 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10152 @*/ 10153 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10154 { 10155 PetscFunctionBegin; 10156 PetscValidType(F, 1); 10157 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10158 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10159 PetscCall(MatFactorFactorizeSchurComplement(F)); 10160 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10161 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10162 PetscFunctionReturn(PETSC_SUCCESS); 10163 } 10164 10165 /*@ 10166 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10167 10168 Logically Collective 10169 10170 Input Parameter: 10171 . F - the factored matrix obtained by calling `MatGetFactor()` 10172 10173 Level: advanced 10174 10175 Note: 10176 Must be called after `MatFactorSetSchurIS()` 10177 10178 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10179 @*/ 10180 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10181 { 10182 MatFactorInfo info; 10183 10184 PetscFunctionBegin; 10185 PetscValidType(F, 1); 10186 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10187 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10188 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10189 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10190 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10191 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10192 } else { 10193 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10194 } 10195 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10196 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10197 PetscFunctionReturn(PETSC_SUCCESS); 10198 } 10199 10200 /*@ 10201 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10202 10203 Neighbor-wise Collective 10204 10205 Input Parameters: 10206 + A - the matrix 10207 . P - the projection matrix 10208 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10209 - 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 10210 if the result is a dense matrix this is irrelevant 10211 10212 Output Parameter: 10213 . C - the product matrix 10214 10215 Level: intermediate 10216 10217 Notes: 10218 C will be created and must be destroyed by the user with `MatDestroy()`. 10219 10220 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10221 10222 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10223 10224 Developer Note: 10225 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10226 10227 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10228 @*/ 10229 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10230 { 10231 PetscFunctionBegin; 10232 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10233 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10234 10235 if (scall == MAT_INITIAL_MATRIX) { 10236 PetscCall(MatProductCreate(A, P, NULL, C)); 10237 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10238 PetscCall(MatProductSetAlgorithm(*C, "default")); 10239 PetscCall(MatProductSetFill(*C, fill)); 10240 10241 (*C)->product->api_user = PETSC_TRUE; 10242 PetscCall(MatProductSetFromOptions(*C)); 10243 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); 10244 PetscCall(MatProductSymbolic(*C)); 10245 } else { /* scall == MAT_REUSE_MATRIX */ 10246 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10247 } 10248 10249 PetscCall(MatProductNumeric(*C)); 10250 (*C)->symmetric = A->symmetric; 10251 (*C)->spd = A->spd; 10252 PetscFunctionReturn(PETSC_SUCCESS); 10253 } 10254 10255 /*@ 10256 MatRARt - Creates the matrix product $C = R * A * R^T$ 10257 10258 Neighbor-wise Collective 10259 10260 Input Parameters: 10261 + A - the matrix 10262 . R - the projection matrix 10263 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10264 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10265 if the result is a dense matrix this is irrelevant 10266 10267 Output Parameter: 10268 . C - the product matrix 10269 10270 Level: intermediate 10271 10272 Notes: 10273 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10274 10275 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10276 10277 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10278 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10279 parallel `MatRARt()` is implemented via explicit transpose of `R`, which could be very expensive. 10280 We recommend using `MatPtAP()`. 10281 10282 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10283 10284 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10285 @*/ 10286 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10287 { 10288 PetscFunctionBegin; 10289 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10290 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10291 10292 if (scall == MAT_INITIAL_MATRIX) { 10293 PetscCall(MatProductCreate(A, R, NULL, C)); 10294 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10295 PetscCall(MatProductSetAlgorithm(*C, "default")); 10296 PetscCall(MatProductSetFill(*C, fill)); 10297 10298 (*C)->product->api_user = PETSC_TRUE; 10299 PetscCall(MatProductSetFromOptions(*C)); 10300 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); 10301 PetscCall(MatProductSymbolic(*C)); 10302 } else { /* scall == MAT_REUSE_MATRIX */ 10303 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10304 } 10305 10306 PetscCall(MatProductNumeric(*C)); 10307 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10308 PetscFunctionReturn(PETSC_SUCCESS); 10309 } 10310 10311 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10312 { 10313 PetscBool flg = PETSC_TRUE; 10314 10315 PetscFunctionBegin; 10316 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10317 if (scall == MAT_INITIAL_MATRIX) { 10318 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10319 PetscCall(MatProductCreate(A, B, NULL, C)); 10320 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10321 PetscCall(MatProductSetFill(*C, fill)); 10322 } else { /* scall == MAT_REUSE_MATRIX */ 10323 Mat_Product *product = (*C)->product; 10324 10325 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10326 if (flg && product && product->type != ptype) { 10327 PetscCall(MatProductClear(*C)); 10328 product = NULL; 10329 } 10330 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10331 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10332 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10333 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10334 product = (*C)->product; 10335 product->fill = fill; 10336 product->clear = PETSC_TRUE; 10337 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10338 flg = PETSC_FALSE; 10339 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10340 } 10341 } 10342 if (flg) { 10343 (*C)->product->api_user = PETSC_TRUE; 10344 PetscCall(MatProductSetType(*C, ptype)); 10345 PetscCall(MatProductSetFromOptions(*C)); 10346 PetscCall(MatProductSymbolic(*C)); 10347 } 10348 PetscCall(MatProductNumeric(*C)); 10349 PetscFunctionReturn(PETSC_SUCCESS); 10350 } 10351 10352 /*@ 10353 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10354 10355 Neighbor-wise Collective 10356 10357 Input Parameters: 10358 + A - the left matrix 10359 . B - the right matrix 10360 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10361 - 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 10362 if the result is a dense matrix this is irrelevant 10363 10364 Output Parameter: 10365 . C - the product matrix 10366 10367 Notes: 10368 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10369 10370 `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 10371 call to this function with `MAT_INITIAL_MATRIX`. 10372 10373 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10374 10375 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`, 10376 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10377 10378 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10379 10380 Example of Usage: 10381 .vb 10382 MatProductCreate(A,B,NULL,&C); 10383 MatProductSetType(C,MATPRODUCT_AB); 10384 MatProductSymbolic(C); 10385 MatProductNumeric(C); // compute C=A * B 10386 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10387 MatProductNumeric(C); 10388 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10389 MatProductNumeric(C); 10390 .ve 10391 10392 Level: intermediate 10393 10394 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10395 @*/ 10396 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10397 { 10398 PetscFunctionBegin; 10399 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10400 PetscFunctionReturn(PETSC_SUCCESS); 10401 } 10402 10403 /*@ 10404 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10405 10406 Neighbor-wise Collective 10407 10408 Input Parameters: 10409 + A - the left matrix 10410 . B - the right matrix 10411 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10412 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10413 10414 Output Parameter: 10415 . C - the product matrix 10416 10417 Options Database Key: 10418 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10419 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10420 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10421 10422 Level: intermediate 10423 10424 Notes: 10425 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10426 10427 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10428 10429 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10430 actually needed. 10431 10432 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10433 and for pairs of `MATMPIDENSE` matrices. 10434 10435 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10436 10437 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10438 10439 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10440 @*/ 10441 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10442 { 10443 PetscFunctionBegin; 10444 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10445 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10446 PetscFunctionReturn(PETSC_SUCCESS); 10447 } 10448 10449 /*@ 10450 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10451 10452 Neighbor-wise Collective 10453 10454 Input Parameters: 10455 + A - the left matrix 10456 . B - the right matrix 10457 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10458 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10459 10460 Output Parameter: 10461 . C - the product matrix 10462 10463 Level: intermediate 10464 10465 Notes: 10466 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10467 10468 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10469 10470 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10471 10472 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10473 actually needed. 10474 10475 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10476 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10477 10478 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10479 10480 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10481 @*/ 10482 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10483 { 10484 PetscFunctionBegin; 10485 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10486 PetscFunctionReturn(PETSC_SUCCESS); 10487 } 10488 10489 /*@ 10490 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10491 10492 Neighbor-wise Collective 10493 10494 Input Parameters: 10495 + A - the left matrix 10496 . B - the middle matrix 10497 . C - the right matrix 10498 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10499 - 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 10500 if the result is a dense matrix this is irrelevant 10501 10502 Output Parameter: 10503 . D - the product matrix 10504 10505 Level: intermediate 10506 10507 Notes: 10508 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10509 10510 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10511 10512 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10513 10514 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10515 actually needed. 10516 10517 If you have many matrices with the same non-zero structure to multiply, you 10518 should use `MAT_REUSE_MATRIX` in all calls but the first 10519 10520 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10521 10522 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10523 @*/ 10524 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10525 { 10526 PetscFunctionBegin; 10527 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10528 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10529 10530 if (scall == MAT_INITIAL_MATRIX) { 10531 PetscCall(MatProductCreate(A, B, C, D)); 10532 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10533 PetscCall(MatProductSetAlgorithm(*D, "default")); 10534 PetscCall(MatProductSetFill(*D, fill)); 10535 10536 (*D)->product->api_user = PETSC_TRUE; 10537 PetscCall(MatProductSetFromOptions(*D)); 10538 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, 10539 ((PetscObject)C)->type_name); 10540 PetscCall(MatProductSymbolic(*D)); 10541 } else { /* user may change input matrices when REUSE */ 10542 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10543 } 10544 PetscCall(MatProductNumeric(*D)); 10545 PetscFunctionReturn(PETSC_SUCCESS); 10546 } 10547 10548 /*@ 10549 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10550 10551 Collective 10552 10553 Input Parameters: 10554 + mat - the matrix 10555 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10556 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10557 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10558 10559 Output Parameter: 10560 . matredundant - redundant matrix 10561 10562 Level: advanced 10563 10564 Notes: 10565 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10566 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10567 10568 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10569 calling it. 10570 10571 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10572 10573 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10574 @*/ 10575 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10576 { 10577 MPI_Comm comm; 10578 PetscMPIInt size; 10579 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10580 Mat_Redundant *redund = NULL; 10581 PetscSubcomm psubcomm = NULL; 10582 MPI_Comm subcomm_in = subcomm; 10583 Mat *matseq; 10584 IS isrow, iscol; 10585 PetscBool newsubcomm = PETSC_FALSE; 10586 10587 PetscFunctionBegin; 10588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10589 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10590 PetscAssertPointer(*matredundant, 5); 10591 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10592 } 10593 10594 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10595 if (size == 1 || nsubcomm == 1) { 10596 if (reuse == MAT_INITIAL_MATRIX) { 10597 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10598 } else { 10599 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"); 10600 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10601 } 10602 PetscFunctionReturn(PETSC_SUCCESS); 10603 } 10604 10605 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10606 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10607 MatCheckPreallocated(mat, 1); 10608 10609 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10610 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10611 /* create psubcomm, then get subcomm */ 10612 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10613 PetscCallMPI(MPI_Comm_size(comm, &size)); 10614 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10615 10616 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10617 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10618 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10619 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10620 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10621 newsubcomm = PETSC_TRUE; 10622 PetscCall(PetscSubcommDestroy(&psubcomm)); 10623 } 10624 10625 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10626 if (reuse == MAT_INITIAL_MATRIX) { 10627 mloc_sub = PETSC_DECIDE; 10628 nloc_sub = PETSC_DECIDE; 10629 if (bs < 1) { 10630 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10631 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10632 } else { 10633 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10634 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10635 } 10636 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10637 rstart = rend - mloc_sub; 10638 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10639 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10640 PetscCall(ISSetIdentity(iscol)); 10641 } else { /* reuse == MAT_REUSE_MATRIX */ 10642 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"); 10643 /* retrieve subcomm */ 10644 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10645 redund = (*matredundant)->redundant; 10646 isrow = redund->isrow; 10647 iscol = redund->iscol; 10648 matseq = redund->matseq; 10649 } 10650 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10651 10652 /* get matredundant over subcomm */ 10653 if (reuse == MAT_INITIAL_MATRIX) { 10654 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10655 10656 /* create a supporting struct and attach it to C for reuse */ 10657 PetscCall(PetscNew(&redund)); 10658 (*matredundant)->redundant = redund; 10659 redund->isrow = isrow; 10660 redund->iscol = iscol; 10661 redund->matseq = matseq; 10662 if (newsubcomm) { 10663 redund->subcomm = subcomm; 10664 } else { 10665 redund->subcomm = MPI_COMM_NULL; 10666 } 10667 } else { 10668 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10669 } 10670 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10671 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10672 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10673 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10674 } 10675 #endif 10676 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10677 PetscFunctionReturn(PETSC_SUCCESS); 10678 } 10679 10680 /*@C 10681 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10682 a given `Mat`. Each submatrix can span multiple procs. 10683 10684 Collective 10685 10686 Input Parameters: 10687 + mat - the matrix 10688 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10689 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10690 10691 Output Parameter: 10692 . subMat - parallel sub-matrices each spanning a given `subcomm` 10693 10694 Level: advanced 10695 10696 Notes: 10697 The submatrix partition across processors is dictated by `subComm` a 10698 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10699 is not restricted to be grouped with consecutive original MPI processes. 10700 10701 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10702 map directly to the layout of the original matrix [wrt the local 10703 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10704 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10705 the `subMat`. However the offDiagMat looses some columns - and this is 10706 reconstructed with `MatSetValues()` 10707 10708 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10709 10710 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10711 @*/ 10712 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10713 { 10714 PetscMPIInt commsize, subCommSize; 10715 10716 PetscFunctionBegin; 10717 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10718 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10719 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10720 10721 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"); 10722 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10723 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10724 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10725 PetscFunctionReturn(PETSC_SUCCESS); 10726 } 10727 10728 /*@ 10729 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10730 10731 Not Collective 10732 10733 Input Parameters: 10734 + mat - matrix to extract local submatrix from 10735 . isrow - local row indices for submatrix 10736 - iscol - local column indices for submatrix 10737 10738 Output Parameter: 10739 . submat - the submatrix 10740 10741 Level: intermediate 10742 10743 Notes: 10744 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10745 10746 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10747 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10748 10749 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10750 `MatSetValuesBlockedLocal()` will also be implemented. 10751 10752 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10753 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10754 10755 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10756 @*/ 10757 PetscErrorCode MatGetLocalSubMatrix(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 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10766 10767 if (mat->ops->getlocalsubmatrix) { 10768 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10769 } else { 10770 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10771 } 10772 PetscFunctionReturn(PETSC_SUCCESS); 10773 } 10774 10775 /*@ 10776 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10777 10778 Not Collective 10779 10780 Input Parameters: 10781 + mat - matrix to extract local submatrix from 10782 . isrow - local row indices for submatrix 10783 . iscol - local column indices for submatrix 10784 - submat - the submatrix 10785 10786 Level: intermediate 10787 10788 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10789 @*/ 10790 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10791 { 10792 PetscFunctionBegin; 10793 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10794 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10795 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10796 PetscCheckSameComm(isrow, 2, iscol, 3); 10797 PetscAssertPointer(submat, 4); 10798 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10799 10800 if (mat->ops->restorelocalsubmatrix) { 10801 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10802 } else { 10803 PetscCall(MatDestroy(submat)); 10804 } 10805 *submat = NULL; 10806 PetscFunctionReturn(PETSC_SUCCESS); 10807 } 10808 10809 /*@ 10810 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10811 10812 Collective 10813 10814 Input Parameter: 10815 . mat - the matrix 10816 10817 Output Parameter: 10818 . is - if any rows have zero diagonals this contains the list of them 10819 10820 Level: developer 10821 10822 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10823 @*/ 10824 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10825 { 10826 PetscFunctionBegin; 10827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10828 PetscValidType(mat, 1); 10829 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10830 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10831 10832 if (!mat->ops->findzerodiagonals) { 10833 Vec diag; 10834 const PetscScalar *a; 10835 PetscInt *rows; 10836 PetscInt rStart, rEnd, r, nrow = 0; 10837 10838 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10839 PetscCall(MatGetDiagonal(mat, diag)); 10840 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10841 PetscCall(VecGetArrayRead(diag, &a)); 10842 for (r = 0; r < rEnd - rStart; ++r) 10843 if (a[r] == 0.0) ++nrow; 10844 PetscCall(PetscMalloc1(nrow, &rows)); 10845 nrow = 0; 10846 for (r = 0; r < rEnd - rStart; ++r) 10847 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10848 PetscCall(VecRestoreArrayRead(diag, &a)); 10849 PetscCall(VecDestroy(&diag)); 10850 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10851 } else { 10852 PetscUseTypeMethod(mat, findzerodiagonals, is); 10853 } 10854 PetscFunctionReturn(PETSC_SUCCESS); 10855 } 10856 10857 /*@ 10858 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10859 10860 Collective 10861 10862 Input Parameter: 10863 . mat - the matrix 10864 10865 Output Parameter: 10866 . is - contains the list of rows with off block diagonal entries 10867 10868 Level: developer 10869 10870 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10871 @*/ 10872 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10873 { 10874 PetscFunctionBegin; 10875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10876 PetscValidType(mat, 1); 10877 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10878 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10879 10880 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10881 PetscFunctionReturn(PETSC_SUCCESS); 10882 } 10883 10884 /*@C 10885 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10886 10887 Collective; No Fortran Support 10888 10889 Input Parameter: 10890 . mat - the matrix 10891 10892 Output Parameter: 10893 . values - the block inverses in column major order (FORTRAN-like) 10894 10895 Level: advanced 10896 10897 Notes: 10898 The size of the blocks is determined by the block size of the matrix. 10899 10900 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10901 10902 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10903 10904 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10905 @*/ 10906 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10907 { 10908 PetscFunctionBegin; 10909 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10910 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10911 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10912 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10913 PetscFunctionReturn(PETSC_SUCCESS); 10914 } 10915 10916 /*@ 10917 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10918 10919 Collective; No Fortran Support 10920 10921 Input Parameters: 10922 + mat - the matrix 10923 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10924 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10925 10926 Output Parameter: 10927 . values - the block inverses in column major order (FORTRAN-like) 10928 10929 Level: advanced 10930 10931 Notes: 10932 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10933 10934 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10935 10936 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10937 @*/ 10938 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10939 { 10940 PetscFunctionBegin; 10941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10942 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10943 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10944 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10945 PetscFunctionReturn(PETSC_SUCCESS); 10946 } 10947 10948 /*@ 10949 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10950 10951 Collective 10952 10953 Input Parameters: 10954 + A - the matrix 10955 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10956 10957 Level: advanced 10958 10959 Note: 10960 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10961 10962 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10963 @*/ 10964 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10965 { 10966 const PetscScalar *vals; 10967 PetscInt *dnnz; 10968 PetscInt m, rstart, rend, bs, i, j; 10969 10970 PetscFunctionBegin; 10971 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10972 PetscCall(MatGetBlockSize(A, &bs)); 10973 PetscCall(MatGetLocalSize(A, &m, NULL)); 10974 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10975 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10976 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10977 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10978 PetscCall(PetscFree(dnnz)); 10979 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10980 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10981 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10982 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10983 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10984 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10985 PetscFunctionReturn(PETSC_SUCCESS); 10986 } 10987 10988 /*@ 10989 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10990 via `MatTransposeColoringCreate()`. 10991 10992 Collective 10993 10994 Input Parameter: 10995 . c - coloring context 10996 10997 Level: intermediate 10998 10999 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 11000 @*/ 11001 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 11002 { 11003 MatTransposeColoring matcolor = *c; 11004 11005 PetscFunctionBegin; 11006 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 11007 if (--((PetscObject)matcolor)->refct > 0) { 11008 matcolor = NULL; 11009 PetscFunctionReturn(PETSC_SUCCESS); 11010 } 11011 11012 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 11013 PetscCall(PetscFree(matcolor->rows)); 11014 PetscCall(PetscFree(matcolor->den2sp)); 11015 PetscCall(PetscFree(matcolor->colorforcol)); 11016 PetscCall(PetscFree(matcolor->columns)); 11017 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 11018 PetscCall(PetscHeaderDestroy(c)); 11019 PetscFunctionReturn(PETSC_SUCCESS); 11020 } 11021 11022 /*@ 11023 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 11024 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 11025 `MatTransposeColoring` to sparse `B`. 11026 11027 Collective 11028 11029 Input Parameters: 11030 + coloring - coloring context created with `MatTransposeColoringCreate()` 11031 - B - sparse matrix 11032 11033 Output Parameter: 11034 . Btdense - dense matrix $B^T$ 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()`, `MatTransColoringApplyDenToSp()` 11042 @*/ 11043 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 11044 { 11045 PetscFunctionBegin; 11046 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11047 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 11048 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 11049 11050 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 11051 PetscFunctionReturn(PETSC_SUCCESS); 11052 } 11053 11054 /*@ 11055 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 11056 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 11057 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 11058 $C_{sp}$ from $C_{den}$. 11059 11060 Collective 11061 11062 Input Parameters: 11063 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 11064 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 11065 11066 Output Parameter: 11067 . Csp - sparse matrix 11068 11069 Level: developer 11070 11071 Note: 11072 These are used internally for some implementations of `MatRARt()` 11073 11074 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11075 @*/ 11076 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11077 { 11078 PetscFunctionBegin; 11079 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11080 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11081 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11082 11083 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11084 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11085 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11086 PetscFunctionReturn(PETSC_SUCCESS); 11087 } 11088 11089 /*@ 11090 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11091 11092 Collective 11093 11094 Input Parameters: 11095 + mat - the matrix product C 11096 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11097 11098 Output Parameter: 11099 . color - the new coloring context 11100 11101 Level: intermediate 11102 11103 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11104 `MatTransColoringApplyDenToSp()` 11105 @*/ 11106 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11107 { 11108 MatTransposeColoring c; 11109 MPI_Comm comm; 11110 11111 PetscFunctionBegin; 11112 PetscAssertPointer(color, 3); 11113 11114 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11115 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11116 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11117 c->ctype = iscoloring->ctype; 11118 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11119 *color = c; 11120 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11121 PetscFunctionReturn(PETSC_SUCCESS); 11122 } 11123 11124 /*@ 11125 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11126 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11127 11128 Not Collective 11129 11130 Input Parameter: 11131 . mat - the matrix 11132 11133 Output Parameter: 11134 . state - the current state 11135 11136 Level: intermediate 11137 11138 Notes: 11139 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11140 different matrices 11141 11142 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11143 11144 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11145 11146 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11147 @*/ 11148 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11149 { 11150 PetscFunctionBegin; 11151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11152 *state = mat->nonzerostate; 11153 PetscFunctionReturn(PETSC_SUCCESS); 11154 } 11155 11156 /*@ 11157 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11158 matrices from each processor 11159 11160 Collective 11161 11162 Input Parameters: 11163 + comm - the communicators the parallel matrix will live on 11164 . seqmat - the input sequential matrices 11165 . n - number of local columns (or `PETSC_DECIDE`) 11166 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11167 11168 Output Parameter: 11169 . mpimat - the parallel matrix generated 11170 11171 Level: developer 11172 11173 Note: 11174 The number of columns of the matrix in EACH processor MUST be the same. 11175 11176 .seealso: [](ch_matrices), `Mat` 11177 @*/ 11178 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11179 { 11180 PetscMPIInt size; 11181 11182 PetscFunctionBegin; 11183 PetscCallMPI(MPI_Comm_size(comm, &size)); 11184 if (size == 1) { 11185 if (reuse == MAT_INITIAL_MATRIX) { 11186 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11187 } else { 11188 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11189 } 11190 PetscFunctionReturn(PETSC_SUCCESS); 11191 } 11192 11193 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"); 11194 11195 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11196 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11197 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11198 PetscFunctionReturn(PETSC_SUCCESS); 11199 } 11200 11201 /*@ 11202 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11203 11204 Collective 11205 11206 Input Parameters: 11207 + A - the matrix to create subdomains from 11208 - N - requested number of subdomains 11209 11210 Output Parameters: 11211 + n - number of subdomains resulting on this MPI process 11212 - iss - `IS` list with indices of subdomains on this MPI process 11213 11214 Level: advanced 11215 11216 Note: 11217 The number of subdomains must be smaller than the communicator size 11218 11219 .seealso: [](ch_matrices), `Mat`, `IS` 11220 @*/ 11221 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11222 { 11223 MPI_Comm comm, subcomm; 11224 PetscMPIInt size, rank, color; 11225 PetscInt rstart, rend, k; 11226 11227 PetscFunctionBegin; 11228 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11229 PetscCallMPI(MPI_Comm_size(comm, &size)); 11230 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11231 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); 11232 *n = 1; 11233 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11234 color = rank / k; 11235 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11236 PetscCall(PetscMalloc1(1, iss)); 11237 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11238 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11239 PetscCallMPI(MPI_Comm_free(&subcomm)); 11240 PetscFunctionReturn(PETSC_SUCCESS); 11241 } 11242 11243 /*@ 11244 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11245 11246 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11247 If they are not the same, uses `MatMatMatMult()`. 11248 11249 Once the coarse grid problem is constructed, correct for interpolation operators 11250 that are not of full rank, which can legitimately happen in the case of non-nested 11251 geometric multigrid. 11252 11253 Input Parameters: 11254 + restrct - restriction operator 11255 . dA - fine grid matrix 11256 . interpolate - interpolation operator 11257 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11258 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11259 11260 Output Parameter: 11261 . A - the Galerkin coarse matrix 11262 11263 Options Database Key: 11264 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11265 11266 Level: developer 11267 11268 Note: 11269 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11270 11271 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11272 @*/ 11273 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11274 { 11275 IS zerorows; 11276 Vec diag; 11277 11278 PetscFunctionBegin; 11279 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11280 /* Construct the coarse grid matrix */ 11281 if (interpolate == restrct) { 11282 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11283 } else { 11284 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11285 } 11286 11287 /* If the interpolation matrix is not of full rank, A will have zero rows. 11288 This can legitimately happen in the case of non-nested geometric multigrid. 11289 In that event, we set the rows of the matrix to the rows of the identity, 11290 ignoring the equations (as the RHS will also be zero). */ 11291 11292 PetscCall(MatFindZeroRows(*A, &zerorows)); 11293 11294 if (zerorows != NULL) { /* if there are any zero rows */ 11295 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11296 PetscCall(MatGetDiagonal(*A, diag)); 11297 PetscCall(VecISSet(diag, zerorows, 1.0)); 11298 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11299 PetscCall(VecDestroy(&diag)); 11300 PetscCall(ISDestroy(&zerorows)); 11301 } 11302 PetscFunctionReturn(PETSC_SUCCESS); 11303 } 11304 11305 /*@C 11306 MatSetOperation - Allows user to set a matrix operation for any matrix type 11307 11308 Logically Collective 11309 11310 Input Parameters: 11311 + mat - the matrix 11312 . op - the name of the operation 11313 - f - the function that provides the operation 11314 11315 Level: developer 11316 11317 Example Usage: 11318 .vb 11319 extern PetscErrorCode usermult(Mat, Vec, Vec); 11320 11321 PetscCall(MatCreateXXX(comm, ..., &A)); 11322 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11323 .ve 11324 11325 Notes: 11326 See the file `include/petscmat.h` for a complete list of matrix 11327 operations, which all have the form MATOP_<OPERATION>, where 11328 <OPERATION> is the name (in all capital letters) of the 11329 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11330 11331 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11332 sequence as the usual matrix interface routines, since they 11333 are intended to be accessed via the usual matrix interface 11334 routines, e.g., 11335 .vb 11336 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11337 .ve 11338 11339 In particular each function MUST return `PETSC_SUCCESS` on success and 11340 nonzero on failure. 11341 11342 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11343 11344 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11345 @*/ 11346 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11347 { 11348 PetscFunctionBegin; 11349 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11350 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11351 (((void (**)(void))mat->ops)[op]) = f; 11352 PetscFunctionReturn(PETSC_SUCCESS); 11353 } 11354 11355 /*@C 11356 MatGetOperation - Gets a matrix operation for any matrix type. 11357 11358 Not Collective 11359 11360 Input Parameters: 11361 + mat - the matrix 11362 - op - the name of the operation 11363 11364 Output Parameter: 11365 . f - the function that provides the operation 11366 11367 Level: developer 11368 11369 Example Usage: 11370 .vb 11371 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11372 11373 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11374 .ve 11375 11376 Notes: 11377 See the file include/petscmat.h for a complete list of matrix 11378 operations, which all have the form MATOP_<OPERATION>, where 11379 <OPERATION> is the name (in all capital letters) of the 11380 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11381 11382 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11383 11384 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11385 @*/ 11386 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11387 { 11388 PetscFunctionBegin; 11389 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11390 *f = (((void (**)(void))mat->ops)[op]); 11391 PetscFunctionReturn(PETSC_SUCCESS); 11392 } 11393 11394 /*@ 11395 MatHasOperation - Determines whether the given matrix supports the particular operation. 11396 11397 Not Collective 11398 11399 Input Parameters: 11400 + mat - the matrix 11401 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11402 11403 Output Parameter: 11404 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11405 11406 Level: advanced 11407 11408 Note: 11409 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11410 11411 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11412 @*/ 11413 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11414 { 11415 PetscFunctionBegin; 11416 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11417 PetscAssertPointer(has, 3); 11418 if (mat->ops->hasoperation) { 11419 PetscUseTypeMethod(mat, hasoperation, op, has); 11420 } else { 11421 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11422 else { 11423 *has = PETSC_FALSE; 11424 if (op == MATOP_CREATE_SUBMATRIX) { 11425 PetscMPIInt size; 11426 11427 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11428 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11429 } 11430 } 11431 } 11432 PetscFunctionReturn(PETSC_SUCCESS); 11433 } 11434 11435 /*@ 11436 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11437 11438 Collective 11439 11440 Input Parameter: 11441 . mat - the matrix 11442 11443 Output Parameter: 11444 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11445 11446 Level: beginner 11447 11448 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11449 @*/ 11450 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11451 { 11452 PetscFunctionBegin; 11453 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11454 PetscValidType(mat, 1); 11455 PetscAssertPointer(cong, 2); 11456 if (!mat->rmap || !mat->cmap) { 11457 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11458 PetscFunctionReturn(PETSC_SUCCESS); 11459 } 11460 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11461 PetscCall(PetscLayoutSetUp(mat->rmap)); 11462 PetscCall(PetscLayoutSetUp(mat->cmap)); 11463 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11464 if (*cong) mat->congruentlayouts = 1; 11465 else mat->congruentlayouts = 0; 11466 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11467 PetscFunctionReturn(PETSC_SUCCESS); 11468 } 11469 11470 PetscErrorCode MatSetInf(Mat A) 11471 { 11472 PetscFunctionBegin; 11473 PetscUseTypeMethod(A, setinf); 11474 PetscFunctionReturn(PETSC_SUCCESS); 11475 } 11476 11477 /*@ 11478 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 11479 and possibly removes small values from the graph structure. 11480 11481 Collective 11482 11483 Input Parameters: 11484 + A - the matrix 11485 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11486 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11487 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11488 . num_idx - size of 'index' array 11489 - index - array of block indices to use for graph strength of connection weight 11490 11491 Output Parameter: 11492 . graph - the resulting graph 11493 11494 Level: advanced 11495 11496 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11497 @*/ 11498 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11499 { 11500 PetscFunctionBegin; 11501 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11502 PetscValidType(A, 1); 11503 PetscValidLogicalCollectiveBool(A, scale, 3); 11504 PetscAssertPointer(graph, 7); 11505 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11506 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11507 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11508 PetscFunctionReturn(PETSC_SUCCESS); 11509 } 11510 11511 /*@ 11512 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11513 meaning the same memory is used for the matrix, and no new memory is allocated. 11514 11515 Collective 11516 11517 Input Parameters: 11518 + A - the matrix 11519 - 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 11520 11521 Level: intermediate 11522 11523 Developer Note: 11524 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11525 of the arrays in the data structure are unneeded. 11526 11527 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11528 @*/ 11529 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11530 { 11531 PetscFunctionBegin; 11532 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11533 PetscUseTypeMethod(A, eliminatezeros, keep); 11534 PetscFunctionReturn(PETSC_SUCCESS); 11535 } 11536