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 preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 936 937 Collective 938 939 Input Parameter: 940 . A - the matrix 941 942 Level: beginner 943 944 Notes: 945 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 946 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 947 makes all of the preallocation space available 948 949 Current values in the matrix are lost in this call. 950 951 Currently only supported for `MATAIJ` matrices. 952 953 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 954 @*/ 955 PetscErrorCode MatResetPreallocation(Mat A) 956 { 957 PetscFunctionBegin; 958 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 959 PetscValidType(A, 1); 960 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()"); 961 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 962 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 963 PetscFunctionReturn(PETSC_SUCCESS); 964 } 965 966 /*@ 967 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 968 969 Collective 970 971 Input Parameter: 972 . A - the matrix 973 974 Level: intermediate 975 976 Notes: 977 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 978 979 Currently only supported for `MATAIJ` matrices. 980 981 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 982 @*/ 983 PetscErrorCode MatResetHash(Mat A) 984 { 985 PetscFunctionBegin; 986 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 987 PetscValidType(A, 1); 988 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()"); 989 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 990 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 991 /* These flags are used to determine whether certain setups occur */ 992 A->was_assembled = PETSC_FALSE; 993 A->assembled = PETSC_FALSE; 994 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 995 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 996 PetscFunctionReturn(PETSC_SUCCESS); 997 } 998 999 /*@ 1000 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 1001 1002 Collective 1003 1004 Input Parameter: 1005 . A - the matrix 1006 1007 Level: advanced 1008 1009 Notes: 1010 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 1011 setting values in the matrix. 1012 1013 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1014 1015 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1016 @*/ 1017 PetscErrorCode MatSetUp(Mat A) 1018 { 1019 PetscFunctionBegin; 1020 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1021 if (!((PetscObject)A)->type_name) { 1022 PetscMPIInt size; 1023 1024 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1025 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1026 } 1027 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1028 PetscCall(PetscLayoutSetUp(A->rmap)); 1029 PetscCall(PetscLayoutSetUp(A->cmap)); 1030 A->preallocated = PETSC_TRUE; 1031 PetscFunctionReturn(PETSC_SUCCESS); 1032 } 1033 1034 #if defined(PETSC_HAVE_SAWS) 1035 #include <petscviewersaws.h> 1036 #endif 1037 1038 /* 1039 If threadsafety is on extraneous matrices may be printed 1040 1041 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1042 */ 1043 #if !defined(PETSC_HAVE_THREADSAFETY) 1044 static PetscInt insidematview = 0; 1045 #endif 1046 1047 /*@ 1048 MatViewFromOptions - View properties of the matrix based on options set in the options database 1049 1050 Collective 1051 1052 Input Parameters: 1053 + A - the matrix 1054 . obj - optional additional object that provides the options prefix to use 1055 - name - command line option 1056 1057 Options Database Key: 1058 . -mat_view [viewertype]:... - the viewer and its options 1059 1060 Level: intermediate 1061 1062 Note: 1063 .vb 1064 If no value is provided ascii:stdout is used 1065 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1066 for example ascii::ascii_info prints just the information about the object not all details 1067 unless :append is given filename opens in write mode, overwriting what was already there 1068 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1069 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1070 socket[:port] defaults to the standard output port 1071 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1072 .ve 1073 1074 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1075 @*/ 1076 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1077 { 1078 PetscFunctionBegin; 1079 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1080 #if !defined(PETSC_HAVE_THREADSAFETY) 1081 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1082 #endif 1083 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1084 PetscFunctionReturn(PETSC_SUCCESS); 1085 } 1086 1087 /*@ 1088 MatView - display information about a matrix in a variety ways 1089 1090 Collective on viewer 1091 1092 Input Parameters: 1093 + mat - the matrix 1094 - viewer - visualization context 1095 1096 Options Database Keys: 1097 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1098 . -mat_view ::ascii_info_detail - Prints more detailed info 1099 . -mat_view - Prints matrix in ASCII format 1100 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1101 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1102 . -display <name> - Sets display name (default is host) 1103 . -draw_pause <sec> - Sets number of seconds to pause after display 1104 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1105 . -viewer_socket_machine <machine> - - 1106 . -viewer_socket_port <port> - - 1107 . -mat_view binary - save matrix to file in binary format 1108 - -viewer_binary_filename <name> - - 1109 1110 Level: beginner 1111 1112 Notes: 1113 The available visualization contexts include 1114 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1115 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1116 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1117 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1118 1119 The user can open alternative visualization contexts with 1120 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1121 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1122 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1123 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1124 1125 The user can call `PetscViewerPushFormat()` to specify the output 1126 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1127 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1128 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1129 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1130 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1131 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1132 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1133 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1134 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1135 1136 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1137 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1138 1139 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1140 1141 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1142 viewer is used. 1143 1144 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1145 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1146 1147 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1148 and then use the following mouse functions. 1149 .vb 1150 left mouse: zoom in 1151 middle mouse: zoom out 1152 right mouse: continue with the simulation 1153 .ve 1154 1155 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1156 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1157 @*/ 1158 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1159 { 1160 PetscInt rows, cols, rbs, cbs; 1161 PetscBool isascii, isstring, issaws; 1162 PetscViewerFormat format; 1163 PetscMPIInt size; 1164 1165 PetscFunctionBegin; 1166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1167 PetscValidType(mat, 1); 1168 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1169 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1170 1171 PetscCall(PetscViewerGetFormat(viewer, &format)); 1172 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1173 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1174 1175 #if !defined(PETSC_HAVE_THREADSAFETY) 1176 insidematview++; 1177 #endif 1178 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1179 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1180 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1181 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"); 1182 1183 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1184 if (isascii) { 1185 if (!mat->preallocated) { 1186 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1187 #if !defined(PETSC_HAVE_THREADSAFETY) 1188 insidematview--; 1189 #endif 1190 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1191 PetscFunctionReturn(PETSC_SUCCESS); 1192 } 1193 if (!mat->assembled) { 1194 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1195 #if !defined(PETSC_HAVE_THREADSAFETY) 1196 insidematview--; 1197 #endif 1198 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1199 PetscFunctionReturn(PETSC_SUCCESS); 1200 } 1201 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1202 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1203 MatNullSpace nullsp, transnullsp; 1204 1205 PetscCall(PetscViewerASCIIPushTab(viewer)); 1206 PetscCall(MatGetSize(mat, &rows, &cols)); 1207 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1208 if (rbs != 1 || cbs != 1) { 1209 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" : "")); 1210 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1211 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1212 if (mat->factortype) { 1213 MatSolverType solver; 1214 PetscCall(MatFactorGetSolverType(mat, &solver)); 1215 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1216 } 1217 if (mat->ops->getinfo) { 1218 MatInfo info; 1219 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1220 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1221 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1222 } 1223 PetscCall(MatGetNullSpace(mat, &nullsp)); 1224 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1225 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1226 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1227 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1228 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1229 PetscCall(PetscViewerASCIIPushTab(viewer)); 1230 PetscCall(MatProductView(mat, viewer)); 1231 PetscCall(PetscViewerASCIIPopTab(viewer)); 1232 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1233 IS tmp; 1234 1235 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1236 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1237 PetscCall(PetscViewerASCIIPushTab(viewer)); 1238 PetscCall(ISView(tmp, viewer)); 1239 PetscCall(PetscViewerASCIIPopTab(viewer)); 1240 PetscCall(ISDestroy(&tmp)); 1241 } 1242 } 1243 } else if (issaws) { 1244 #if defined(PETSC_HAVE_SAWS) 1245 PetscMPIInt rank; 1246 1247 PetscCall(PetscObjectName((PetscObject)mat)); 1248 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1249 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1250 #endif 1251 } else if (isstring) { 1252 const char *type; 1253 PetscCall(MatGetType(mat, &type)); 1254 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1255 PetscTryTypeMethod(mat, view, viewer); 1256 } 1257 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1258 PetscCall(PetscViewerASCIIPushTab(viewer)); 1259 PetscUseTypeMethod(mat, viewnative, viewer); 1260 PetscCall(PetscViewerASCIIPopTab(viewer)); 1261 } else if (mat->ops->view) { 1262 PetscCall(PetscViewerASCIIPushTab(viewer)); 1263 PetscUseTypeMethod(mat, view, viewer); 1264 PetscCall(PetscViewerASCIIPopTab(viewer)); 1265 } 1266 if (isascii) { 1267 PetscCall(PetscViewerGetFormat(viewer, &format)); 1268 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1269 } 1270 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1271 #if !defined(PETSC_HAVE_THREADSAFETY) 1272 insidematview--; 1273 #endif 1274 PetscFunctionReturn(PETSC_SUCCESS); 1275 } 1276 1277 #if defined(PETSC_USE_DEBUG) 1278 #include <../src/sys/totalview/tv_data_display.h> 1279 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1280 { 1281 TV_add_row("Local rows", "int", &mat->rmap->n); 1282 TV_add_row("Local columns", "int", &mat->cmap->n); 1283 TV_add_row("Global rows", "int", &mat->rmap->N); 1284 TV_add_row("Global columns", "int", &mat->cmap->N); 1285 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1286 return TV_format_OK; 1287 } 1288 #endif 1289 1290 /*@ 1291 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1292 with `MatView()`. The matrix format is determined from the options database. 1293 Generates a parallel MPI matrix if the communicator has more than one 1294 processor. The default matrix type is `MATAIJ`. 1295 1296 Collective 1297 1298 Input Parameters: 1299 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1300 or some related function before a call to `MatLoad()` 1301 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1302 1303 Options Database Key: 1304 . -matload_block_size <bs> - set block size 1305 1306 Level: beginner 1307 1308 Notes: 1309 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1310 `Mat` before calling this routine if you wish to set it from the options database. 1311 1312 `MatLoad()` automatically loads into the options database any options 1313 given in the file filename.info where filename is the name of the file 1314 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1315 file will be ignored if you use the -viewer_binary_skip_info option. 1316 1317 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1318 sets the default matrix type AIJ and sets the local and global sizes. 1319 If type and/or size is already set, then the same are used. 1320 1321 In parallel, each processor can load a subset of rows (or the 1322 entire matrix). This routine is especially useful when a large 1323 matrix is stored on disk and only part of it is desired on each 1324 processor. For example, a parallel solver may access only some of 1325 the rows from each processor. The algorithm used here reads 1326 relatively small blocks of data rather than reading the entire 1327 matrix and then subsetting it. 1328 1329 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1330 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1331 or the sequence like 1332 .vb 1333 `PetscViewer` v; 1334 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1335 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1336 `PetscViewerSetFromOptions`(v); 1337 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1338 `PetscViewerFileSetName`(v,"datafile"); 1339 .ve 1340 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1341 $ -viewer_type {binary, hdf5} 1342 1343 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1344 and src/mat/tutorials/ex10.c with the second approach. 1345 1346 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1347 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1348 Multiple objects, both matrices and vectors, can be stored within the same file. 1349 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1350 1351 Most users should not need to know the details of the binary storage 1352 format, since `MatLoad()` and `MatView()` completely hide these details. 1353 But for anyone who is interested, the standard binary matrix storage 1354 format is 1355 1356 .vb 1357 PetscInt MAT_FILE_CLASSID 1358 PetscInt number of rows 1359 PetscInt number of columns 1360 PetscInt total number of nonzeros 1361 PetscInt *number nonzeros in each row 1362 PetscInt *column indices of all nonzeros (starting index is zero) 1363 PetscScalar *values of all nonzeros 1364 .ve 1365 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1366 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 1367 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1368 1369 PETSc automatically does the byte swapping for 1370 machines that store the bytes reversed. Thus if you write your own binary 1371 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1372 and `PetscBinaryWrite()` to see how this may be done. 1373 1374 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1375 Each processor's chunk is loaded independently by its owning MPI process. 1376 Multiple objects, both matrices and vectors, can be stored within the same file. 1377 They are looked up by their PetscObject name. 1378 1379 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1380 by default the same structure and naming of the AIJ arrays and column count 1381 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1382 $ save example.mat A b -v7.3 1383 can be directly read by this routine (see Reference 1 for details). 1384 1385 Depending on your MATLAB version, this format might be a default, 1386 otherwise you can set it as default in Preferences. 1387 1388 Unless -nocompression flag is used to save the file in MATLAB, 1389 PETSc must be configured with ZLIB package. 1390 1391 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1392 1393 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1394 1395 Corresponding `MatView()` is not yet implemented. 1396 1397 The loaded matrix is actually a transpose of the original one in MATLAB, 1398 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1399 With this format, matrix is automatically transposed by PETSc, 1400 unless the matrix is marked as SPD or symmetric 1401 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1402 1403 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1404 1405 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1406 @*/ 1407 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1408 { 1409 PetscBool flg; 1410 1411 PetscFunctionBegin; 1412 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1413 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1414 1415 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1416 1417 flg = PETSC_FALSE; 1418 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1419 if (flg) { 1420 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1421 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1422 } 1423 flg = PETSC_FALSE; 1424 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1425 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1426 1427 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1428 PetscUseTypeMethod(mat, load, viewer); 1429 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1430 PetscFunctionReturn(PETSC_SUCCESS); 1431 } 1432 1433 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1434 { 1435 Mat_Redundant *redund = *redundant; 1436 1437 PetscFunctionBegin; 1438 if (redund) { 1439 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1440 PetscCall(ISDestroy(&redund->isrow)); 1441 PetscCall(ISDestroy(&redund->iscol)); 1442 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1443 } else { 1444 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1445 PetscCall(PetscFree(redund->sbuf_j)); 1446 PetscCall(PetscFree(redund->sbuf_a)); 1447 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1448 PetscCall(PetscFree(redund->rbuf_j[i])); 1449 PetscCall(PetscFree(redund->rbuf_a[i])); 1450 } 1451 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1452 } 1453 1454 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1455 PetscCall(PetscFree(redund)); 1456 } 1457 PetscFunctionReturn(PETSC_SUCCESS); 1458 } 1459 1460 /*@ 1461 MatDestroy - Frees space taken by a matrix. 1462 1463 Collective 1464 1465 Input Parameter: 1466 . A - the matrix 1467 1468 Level: beginner 1469 1470 Developer Note: 1471 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1472 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1473 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1474 if changes are needed here. 1475 1476 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1477 @*/ 1478 PetscErrorCode MatDestroy(Mat *A) 1479 { 1480 PetscFunctionBegin; 1481 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1482 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1483 if (--((PetscObject)*A)->refct > 0) { 1484 *A = NULL; 1485 PetscFunctionReturn(PETSC_SUCCESS); 1486 } 1487 1488 /* if memory was published with SAWs then destroy it */ 1489 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1490 PetscTryTypeMethod(*A, destroy); 1491 1492 PetscCall(PetscFree((*A)->factorprefix)); 1493 PetscCall(PetscFree((*A)->defaultvectype)); 1494 PetscCall(PetscFree((*A)->defaultrandtype)); 1495 PetscCall(PetscFree((*A)->bsizes)); 1496 PetscCall(PetscFree((*A)->solvertype)); 1497 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1498 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1499 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1500 PetscCall(MatProductClear(*A)); 1501 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1502 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1503 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1504 PetscCall(MatDestroy(&(*A)->schur)); 1505 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1506 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1507 PetscCall(PetscHeaderDestroy(A)); 1508 PetscFunctionReturn(PETSC_SUCCESS); 1509 } 1510 1511 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1512 /*@ 1513 MatSetValues - Inserts or adds a block of values into a matrix. 1514 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1515 MUST be called after all calls to `MatSetValues()` have been completed. 1516 1517 Not Collective 1518 1519 Input Parameters: 1520 + mat - the matrix 1521 . v - a logically two-dimensional array of values 1522 . m - the number of rows 1523 . idxm - the global indices of the rows 1524 . n - the number of columns 1525 . idxn - the global indices of the columns 1526 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1527 1528 Level: beginner 1529 1530 Notes: 1531 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1532 1533 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1534 options cannot be mixed without intervening calls to the assembly 1535 routines. 1536 1537 `MatSetValues()` uses 0-based row and column numbers in Fortran 1538 as well as in C. 1539 1540 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1541 simply ignored. This allows easily inserting element stiffness matrices 1542 with homogeneous Dirichlet boundary conditions that you don't want represented 1543 in the matrix. 1544 1545 Efficiency Alert: 1546 The routine `MatSetValuesBlocked()` may offer much better efficiency 1547 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1548 1549 Fortran Notes: 1550 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1551 .vb 1552 MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 1553 .ve 1554 1555 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1556 1557 Developer Note: 1558 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1559 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1560 1561 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1562 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1563 @*/ 1564 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1565 { 1566 PetscFunctionBeginHot; 1567 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1568 PetscValidType(mat, 1); 1569 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1570 PetscAssertPointer(idxm, 3); 1571 PetscAssertPointer(idxn, 5); 1572 MatCheckPreallocated(mat, 1); 1573 1574 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1575 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1576 1577 if (PetscDefined(USE_DEBUG)) { 1578 PetscInt i, j; 1579 1580 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1581 if (v) { 1582 for (i = 0; i < m; i++) { 1583 for (j = 0; j < n; j++) { 1584 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1585 #if defined(PETSC_USE_COMPLEX) 1586 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]); 1587 #else 1588 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]); 1589 #endif 1590 } 1591 } 1592 } 1593 for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1); 1594 for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1); 1595 } 1596 1597 if (mat->assembled) { 1598 mat->was_assembled = PETSC_TRUE; 1599 mat->assembled = PETSC_FALSE; 1600 } 1601 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1602 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1603 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1604 PetscFunctionReturn(PETSC_SUCCESS); 1605 } 1606 1607 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1608 /*@ 1609 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1610 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1611 MUST be called after all calls to `MatSetValues()` have been completed. 1612 1613 Not Collective 1614 1615 Input Parameters: 1616 + mat - the matrix 1617 . v - a logically two-dimensional array of values 1618 . ism - the rows to provide 1619 . isn - the columns to provide 1620 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1621 1622 Level: beginner 1623 1624 Notes: 1625 By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options. 1626 1627 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1628 options cannot be mixed without intervening calls to the assembly 1629 routines. 1630 1631 `MatSetValues()` uses 0-based row and column numbers in Fortran 1632 as well as in C. 1633 1634 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1635 simply ignored. This allows easily inserting element stiffness matrices 1636 with homogeneous Dirichlet boundary conditions that you don't want represented 1637 in the matrix. 1638 1639 Efficiency Alert: 1640 The routine `MatSetValuesBlocked()` may offer much better efficiency 1641 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1642 1643 This is currently not optimized for any particular `ISType` 1644 1645 Developer Note: 1646 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1647 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1648 1649 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1650 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1651 @*/ 1652 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1653 { 1654 PetscInt m, n; 1655 const PetscInt *rows, *cols; 1656 1657 PetscFunctionBeginHot; 1658 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1659 PetscCall(ISGetIndices(ism, &rows)); 1660 PetscCall(ISGetIndices(isn, &cols)); 1661 PetscCall(ISGetLocalSize(ism, &m)); 1662 PetscCall(ISGetLocalSize(isn, &n)); 1663 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1664 PetscCall(ISRestoreIndices(ism, &rows)); 1665 PetscCall(ISRestoreIndices(isn, &cols)); 1666 PetscFunctionReturn(PETSC_SUCCESS); 1667 } 1668 1669 /*@ 1670 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1671 values into a matrix 1672 1673 Not Collective 1674 1675 Input Parameters: 1676 + mat - the matrix 1677 . row - the (block) row to set 1678 - v - a logically two-dimensional array of values 1679 1680 Level: intermediate 1681 1682 Notes: 1683 The values, `v`, are column-oriented (for the block version) and sorted 1684 1685 All the nonzero values in `row` must be provided 1686 1687 The matrix must have previously had its column indices set, likely by having been assembled. 1688 1689 `row` must belong to this MPI process 1690 1691 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1692 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1693 @*/ 1694 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1695 { 1696 PetscInt globalrow; 1697 1698 PetscFunctionBegin; 1699 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1700 PetscValidType(mat, 1); 1701 PetscAssertPointer(v, 3); 1702 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1703 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1704 PetscFunctionReturn(PETSC_SUCCESS); 1705 } 1706 1707 /*@ 1708 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1709 values into a matrix 1710 1711 Not Collective 1712 1713 Input Parameters: 1714 + mat - the matrix 1715 . row - the (block) row to set 1716 - 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 1717 1718 Level: advanced 1719 1720 Notes: 1721 The values, `v`, are column-oriented for the block version. 1722 1723 All the nonzeros in `row` must be provided 1724 1725 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1726 1727 `row` must belong to this process 1728 1729 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1730 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1731 @*/ 1732 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1733 { 1734 PetscFunctionBeginHot; 1735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1736 PetscValidType(mat, 1); 1737 MatCheckPreallocated(mat, 1); 1738 PetscAssertPointer(v, 3); 1739 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1740 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1741 mat->insertmode = INSERT_VALUES; 1742 1743 if (mat->assembled) { 1744 mat->was_assembled = PETSC_TRUE; 1745 mat->assembled = PETSC_FALSE; 1746 } 1747 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1748 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1749 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1750 PetscFunctionReturn(PETSC_SUCCESS); 1751 } 1752 1753 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1754 /*@ 1755 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1756 Using structured grid indexing 1757 1758 Not Collective 1759 1760 Input Parameters: 1761 + mat - the matrix 1762 . m - number of rows being entered 1763 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1764 . n - number of columns being entered 1765 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1766 . v - a logically two-dimensional array of values 1767 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1768 1769 Level: beginner 1770 1771 Notes: 1772 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1773 1774 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1775 options cannot be mixed without intervening calls to the assembly 1776 routines. 1777 1778 The grid coordinates are across the entire grid, not just the local portion 1779 1780 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1781 as well as in C. 1782 1783 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1784 1785 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1786 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1787 1788 The columns and rows in the stencil passed in MUST be contained within the 1789 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1790 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1791 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1792 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1793 1794 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1795 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1796 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1797 `DM_BOUNDARY_PERIODIC` boundary type. 1798 1799 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 1800 a single value per point) you can skip filling those indices. 1801 1802 Inspired by the structured grid interface to the HYPRE package 1803 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1804 1805 Efficiency Alert: 1806 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1807 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1808 1809 Fortran Note: 1810 `idxm` and `idxn` should be declared as 1811 $ MatStencil idxm(4,m),idxn(4,n) 1812 and the values inserted using 1813 .vb 1814 idxm(MatStencil_i,1) = i 1815 idxm(MatStencil_j,1) = j 1816 idxm(MatStencil_k,1) = k 1817 idxm(MatStencil_c,1) = c 1818 etc 1819 .ve 1820 1821 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1822 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1823 @*/ 1824 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1825 { 1826 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1827 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1828 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1829 1830 PetscFunctionBegin; 1831 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1832 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1833 PetscValidType(mat, 1); 1834 PetscAssertPointer(idxm, 3); 1835 PetscAssertPointer(idxn, 5); 1836 1837 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1838 jdxm = buf; 1839 jdxn = buf + m; 1840 } else { 1841 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1842 jdxm = bufm; 1843 jdxn = bufn; 1844 } 1845 for (i = 0; i < m; i++) { 1846 for (j = 0; j < 3 - sdim; j++) dxm++; 1847 tmp = *dxm++ - starts[0]; 1848 for (j = 0; j < dim - 1; j++) { 1849 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1850 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1851 } 1852 if (mat->stencil.noc) dxm++; 1853 jdxm[i] = tmp; 1854 } 1855 for (i = 0; i < n; i++) { 1856 for (j = 0; j < 3 - sdim; j++) dxn++; 1857 tmp = *dxn++ - starts[0]; 1858 for (j = 0; j < dim - 1; j++) { 1859 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1860 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1861 } 1862 if (mat->stencil.noc) dxn++; 1863 jdxn[i] = tmp; 1864 } 1865 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1866 PetscCall(PetscFree2(bufm, bufn)); 1867 PetscFunctionReturn(PETSC_SUCCESS); 1868 } 1869 1870 /*@ 1871 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1872 Using structured grid indexing 1873 1874 Not Collective 1875 1876 Input Parameters: 1877 + mat - the matrix 1878 . m - number of rows being entered 1879 . idxm - grid coordinates for matrix rows being entered 1880 . n - number of columns being entered 1881 . idxn - grid coordinates for matrix columns being entered 1882 . v - a logically two-dimensional array of values 1883 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1884 1885 Level: beginner 1886 1887 Notes: 1888 By default the values, `v`, are row-oriented and unsorted. 1889 See `MatSetOption()` for other options. 1890 1891 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1892 options cannot be mixed without intervening calls to the assembly 1893 routines. 1894 1895 The grid coordinates are across the entire grid, not just the local portion 1896 1897 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1898 as well as in C. 1899 1900 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1901 1902 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1903 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1904 1905 The columns and rows in the stencil passed in MUST be contained within the 1906 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1907 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1908 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1909 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1910 1911 Negative indices may be passed in idxm and idxn, these rows and columns are 1912 simply ignored. This allows easily inserting element stiffness matrices 1913 with homogeneous Dirichlet boundary conditions that you don't want represented 1914 in the matrix. 1915 1916 Inspired by the structured grid interface to the HYPRE package 1917 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1918 1919 Fortran Note: 1920 `idxm` and `idxn` should be declared as 1921 $ MatStencil idxm(4,m),idxn(4,n) 1922 and the values inserted using 1923 .vb 1924 idxm(MatStencil_i,1) = i 1925 idxm(MatStencil_j,1) = j 1926 idxm(MatStencil_k,1) = k 1927 etc 1928 .ve 1929 1930 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1931 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1932 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1933 @*/ 1934 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1935 { 1936 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1937 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1938 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1939 1940 PetscFunctionBegin; 1941 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1942 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1943 PetscValidType(mat, 1); 1944 PetscAssertPointer(idxm, 3); 1945 PetscAssertPointer(idxn, 5); 1946 PetscAssertPointer(v, 6); 1947 1948 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1949 jdxm = buf; 1950 jdxn = buf + m; 1951 } else { 1952 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1953 jdxm = bufm; 1954 jdxn = bufn; 1955 } 1956 for (i = 0; i < m; i++) { 1957 for (j = 0; j < 3 - sdim; j++) dxm++; 1958 tmp = *dxm++ - starts[0]; 1959 for (j = 0; j < sdim - 1; j++) { 1960 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1961 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1962 } 1963 dxm++; 1964 jdxm[i] = tmp; 1965 } 1966 for (i = 0; i < n; i++) { 1967 for (j = 0; j < 3 - sdim; j++) dxn++; 1968 tmp = *dxn++ - starts[0]; 1969 for (j = 0; j < sdim - 1; j++) { 1970 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1971 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1972 } 1973 dxn++; 1974 jdxn[i] = tmp; 1975 } 1976 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1977 PetscCall(PetscFree2(bufm, bufn)); 1978 PetscFunctionReturn(PETSC_SUCCESS); 1979 } 1980 1981 /*@ 1982 MatSetStencil - Sets the grid information for setting values into a matrix via 1983 `MatSetValuesStencil()` 1984 1985 Not Collective 1986 1987 Input Parameters: 1988 + mat - the matrix 1989 . dim - dimension of the grid 1, 2, or 3 1990 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1991 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1992 - dof - number of degrees of freedom per node 1993 1994 Level: beginner 1995 1996 Notes: 1997 Inspired by the structured grid interface to the HYPRE package 1998 (www.llnl.gov/CASC/hyper) 1999 2000 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 2001 user. 2002 2003 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 2004 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 2005 @*/ 2006 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 2007 { 2008 PetscFunctionBegin; 2009 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2010 PetscAssertPointer(dims, 3); 2011 PetscAssertPointer(starts, 4); 2012 2013 mat->stencil.dim = dim + (dof > 1); 2014 for (PetscInt i = 0; i < dim; i++) { 2015 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 2016 mat->stencil.starts[i] = starts[dim - i - 1]; 2017 } 2018 mat->stencil.dims[dim] = dof; 2019 mat->stencil.starts[dim] = 0; 2020 mat->stencil.noc = (PetscBool)(dof == 1); 2021 PetscFunctionReturn(PETSC_SUCCESS); 2022 } 2023 2024 /*@ 2025 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2026 2027 Not Collective 2028 2029 Input Parameters: 2030 + mat - the matrix 2031 . v - a logically two-dimensional array of values 2032 . m - the number of block rows 2033 . idxm - the global block indices 2034 . n - the number of block columns 2035 . idxn - the global block indices 2036 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2037 2038 Level: intermediate 2039 2040 Notes: 2041 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2042 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2043 2044 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2045 NOT the total number of rows/columns; for example, if the block size is 2 and 2046 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2047 The values in `idxm` would be 1 2; that is the first index for each block divided by 2048 the block size. 2049 2050 You must call `MatSetBlockSize()` when constructing this matrix (before 2051 preallocating it). 2052 2053 By default the values, `v`, are row-oriented, so the layout of 2054 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2055 2056 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2057 options cannot be mixed without intervening calls to the assembly 2058 routines. 2059 2060 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2061 as well as in C. 2062 2063 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2064 simply ignored. This allows easily inserting element stiffness matrices 2065 with homogeneous Dirichlet boundary conditions that you don't want represented 2066 in the matrix. 2067 2068 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2069 internal searching must be done to determine where to place the 2070 data in the matrix storage space. By instead inserting blocks of 2071 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2072 reduced. 2073 2074 Example: 2075 .vb 2076 Suppose m=n=2 and block size(bs) = 2 The array is 2077 2078 1 2 | 3 4 2079 5 6 | 7 8 2080 - - - | - - - 2081 9 10 | 11 12 2082 13 14 | 15 16 2083 2084 v[] should be passed in like 2085 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2086 2087 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2088 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2089 .ve 2090 2091 Fortran Notes: 2092 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2093 .vb 2094 MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES) 2095 .ve 2096 2097 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2098 2099 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2100 @*/ 2101 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2102 { 2103 PetscFunctionBeginHot; 2104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2105 PetscValidType(mat, 1); 2106 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2107 PetscAssertPointer(idxm, 3); 2108 PetscAssertPointer(idxn, 5); 2109 MatCheckPreallocated(mat, 1); 2110 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2111 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2112 if (PetscDefined(USE_DEBUG)) { 2113 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2114 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2115 } 2116 if (PetscDefined(USE_DEBUG)) { 2117 PetscInt rbs, cbs, M, N, i; 2118 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2119 PetscCall(MatGetSize(mat, &M, &N)); 2120 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); 2121 for (i = 0; i < n; i++) 2122 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); 2123 } 2124 if (mat->assembled) { 2125 mat->was_assembled = PETSC_TRUE; 2126 mat->assembled = PETSC_FALSE; 2127 } 2128 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2129 if (mat->ops->setvaluesblocked) { 2130 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2131 } else { 2132 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2133 PetscInt i, j, bs, cbs; 2134 2135 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2136 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2137 iidxm = buf; 2138 iidxn = buf + m * bs; 2139 } else { 2140 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2141 iidxm = bufr; 2142 iidxn = bufc; 2143 } 2144 for (i = 0; i < m; i++) { 2145 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2146 } 2147 if (m != n || bs != cbs || idxm != idxn) { 2148 for (i = 0; i < n; i++) { 2149 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2150 } 2151 } else iidxn = iidxm; 2152 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2153 PetscCall(PetscFree2(bufr, bufc)); 2154 } 2155 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2156 PetscFunctionReturn(PETSC_SUCCESS); 2157 } 2158 2159 /*@ 2160 MatGetValues - Gets a block of local values from a matrix. 2161 2162 Not Collective; can only return values that are owned by the give process 2163 2164 Input Parameters: 2165 + mat - the matrix 2166 . v - a logically two-dimensional array for storing the values 2167 . m - the number of rows 2168 . idxm - the global indices of the rows 2169 . n - the number of columns 2170 - idxn - the global indices of the columns 2171 2172 Level: advanced 2173 2174 Notes: 2175 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2176 The values, `v`, are then returned in a row-oriented format, 2177 analogous to that used by default in `MatSetValues()`. 2178 2179 `MatGetValues()` uses 0-based row and column numbers in 2180 Fortran as well as in C. 2181 2182 `MatGetValues()` requires that the matrix has been assembled 2183 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2184 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2185 without intermediate matrix assembly. 2186 2187 Negative row or column indices will be ignored and those locations in `v` will be 2188 left unchanged. 2189 2190 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2191 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2192 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2193 2194 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2195 @*/ 2196 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2197 { 2198 PetscFunctionBegin; 2199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2200 PetscValidType(mat, 1); 2201 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2202 PetscAssertPointer(idxm, 3); 2203 PetscAssertPointer(idxn, 5); 2204 PetscAssertPointer(v, 6); 2205 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2206 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2207 MatCheckPreallocated(mat, 1); 2208 2209 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2210 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2211 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2212 PetscFunctionReturn(PETSC_SUCCESS); 2213 } 2214 2215 /*@ 2216 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2217 defined previously by `MatSetLocalToGlobalMapping()` 2218 2219 Not Collective 2220 2221 Input Parameters: 2222 + mat - the matrix 2223 . nrow - number of rows 2224 . irow - the row local indices 2225 . ncol - number of columns 2226 - icol - the column local indices 2227 2228 Output Parameter: 2229 . y - a logically two-dimensional array of values 2230 2231 Level: advanced 2232 2233 Notes: 2234 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2235 2236 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, 2237 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2238 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2239 with `MatSetLocalToGlobalMapping()`. 2240 2241 Developer Note: 2242 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2243 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2244 2245 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2246 `MatSetValuesLocal()`, `MatGetValues()` 2247 @*/ 2248 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2249 { 2250 PetscFunctionBeginHot; 2251 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2252 PetscValidType(mat, 1); 2253 MatCheckPreallocated(mat, 1); 2254 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2255 PetscAssertPointer(irow, 3); 2256 PetscAssertPointer(icol, 5); 2257 if (PetscDefined(USE_DEBUG)) { 2258 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2259 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2260 } 2261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2262 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2263 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2264 else { 2265 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2266 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2267 irowm = buf; 2268 icolm = buf + nrow; 2269 } else { 2270 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2271 irowm = bufr; 2272 icolm = bufc; 2273 } 2274 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2275 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2276 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2277 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2278 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2279 PetscCall(PetscFree2(bufr, bufc)); 2280 } 2281 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2282 PetscFunctionReturn(PETSC_SUCCESS); 2283 } 2284 2285 /*@ 2286 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2287 the same size. Currently, this can only be called once and creates the given matrix. 2288 2289 Not Collective 2290 2291 Input Parameters: 2292 + mat - the matrix 2293 . nb - the number of blocks 2294 . bs - the number of rows (and columns) in each block 2295 . rows - a concatenation of the rows for each block 2296 - v - a concatenation of logically two-dimensional arrays of values 2297 2298 Level: advanced 2299 2300 Notes: 2301 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2302 2303 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2304 2305 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2306 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2307 @*/ 2308 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2309 { 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2312 PetscValidType(mat, 1); 2313 PetscAssertPointer(rows, 4); 2314 PetscAssertPointer(v, 5); 2315 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2316 2317 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2318 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2319 else { 2320 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2321 } 2322 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2323 PetscFunctionReturn(PETSC_SUCCESS); 2324 } 2325 2326 /*@ 2327 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2328 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2329 using a local (per-processor) numbering. 2330 2331 Not Collective 2332 2333 Input Parameters: 2334 + x - the matrix 2335 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2336 - cmapping - column mapping 2337 2338 Level: intermediate 2339 2340 Note: 2341 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2342 2343 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2344 @*/ 2345 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2346 { 2347 PetscFunctionBegin; 2348 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2349 PetscValidType(x, 1); 2350 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2351 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2352 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2353 else { 2354 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2355 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2356 } 2357 PetscFunctionReturn(PETSC_SUCCESS); 2358 } 2359 2360 /*@ 2361 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2362 2363 Not Collective 2364 2365 Input Parameter: 2366 . A - the matrix 2367 2368 Output Parameters: 2369 + rmapping - row mapping 2370 - cmapping - column mapping 2371 2372 Level: advanced 2373 2374 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2375 @*/ 2376 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2377 { 2378 PetscFunctionBegin; 2379 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2380 PetscValidType(A, 1); 2381 if (rmapping) { 2382 PetscAssertPointer(rmapping, 2); 2383 *rmapping = A->rmap->mapping; 2384 } 2385 if (cmapping) { 2386 PetscAssertPointer(cmapping, 3); 2387 *cmapping = A->cmap->mapping; 2388 } 2389 PetscFunctionReturn(PETSC_SUCCESS); 2390 } 2391 2392 /*@ 2393 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2394 2395 Logically Collective 2396 2397 Input Parameters: 2398 + A - the matrix 2399 . rmap - row layout 2400 - cmap - column layout 2401 2402 Level: advanced 2403 2404 Note: 2405 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2406 2407 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2408 @*/ 2409 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2410 { 2411 PetscFunctionBegin; 2412 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2413 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2414 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2415 PetscFunctionReturn(PETSC_SUCCESS); 2416 } 2417 2418 /*@ 2419 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2420 2421 Not Collective 2422 2423 Input Parameter: 2424 . A - the matrix 2425 2426 Output Parameters: 2427 + rmap - row layout 2428 - cmap - column layout 2429 2430 Level: advanced 2431 2432 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2433 @*/ 2434 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2435 { 2436 PetscFunctionBegin; 2437 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2438 PetscValidType(A, 1); 2439 if (rmap) { 2440 PetscAssertPointer(rmap, 2); 2441 *rmap = A->rmap; 2442 } 2443 if (cmap) { 2444 PetscAssertPointer(cmap, 3); 2445 *cmap = A->cmap; 2446 } 2447 PetscFunctionReturn(PETSC_SUCCESS); 2448 } 2449 2450 /*@ 2451 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2452 using a local numbering of the rows and columns. 2453 2454 Not Collective 2455 2456 Input Parameters: 2457 + mat - the matrix 2458 . nrow - number of rows 2459 . irow - the row local indices 2460 . ncol - number of columns 2461 . icol - the column local indices 2462 . y - a logically two-dimensional array of values 2463 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2464 2465 Level: intermediate 2466 2467 Notes: 2468 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2469 2470 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2471 options cannot be mixed without intervening calls to the assembly 2472 routines. 2473 2474 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2475 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2476 2477 Fortran Notes: 2478 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2479 .vb 2480 MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2481 .ve 2482 2483 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2484 2485 Developer Note: 2486 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2487 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2488 2489 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2490 `MatGetValuesLocal()` 2491 @*/ 2492 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2493 { 2494 PetscFunctionBeginHot; 2495 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2496 PetscValidType(mat, 1); 2497 MatCheckPreallocated(mat, 1); 2498 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2499 PetscAssertPointer(irow, 3); 2500 PetscAssertPointer(icol, 5); 2501 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2502 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2503 if (PetscDefined(USE_DEBUG)) { 2504 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2505 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2506 } 2507 2508 if (mat->assembled) { 2509 mat->was_assembled = PETSC_TRUE; 2510 mat->assembled = PETSC_FALSE; 2511 } 2512 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2513 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2514 else { 2515 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2516 const PetscInt *irowm, *icolm; 2517 2518 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2519 bufr = buf; 2520 bufc = buf + nrow; 2521 irowm = bufr; 2522 icolm = bufc; 2523 } else { 2524 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2525 irowm = bufr; 2526 icolm = bufc; 2527 } 2528 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2529 else irowm = irow; 2530 if (mat->cmap->mapping) { 2531 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2532 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2533 } else icolm = irowm; 2534 } else icolm = icol; 2535 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2536 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2537 } 2538 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2539 PetscFunctionReturn(PETSC_SUCCESS); 2540 } 2541 2542 /*@ 2543 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2544 using a local ordering of the nodes a block at a time. 2545 2546 Not Collective 2547 2548 Input Parameters: 2549 + mat - the matrix 2550 . nrow - number of rows 2551 . irow - the row local indices 2552 . ncol - number of columns 2553 . icol - the column local indices 2554 . y - a logically two-dimensional array of values 2555 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2556 2557 Level: intermediate 2558 2559 Notes: 2560 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2561 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2562 2563 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2564 options cannot be mixed without intervening calls to the assembly 2565 routines. 2566 2567 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2568 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2569 2570 Fortran Notes: 2571 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2572 .vb 2573 MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES) 2574 .ve 2575 2576 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2577 2578 Developer Note: 2579 This is labeled with C so does not automatically generate Fortran stubs and interfaces 2580 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2581 2582 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2583 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2584 @*/ 2585 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2586 { 2587 PetscFunctionBeginHot; 2588 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2589 PetscValidType(mat, 1); 2590 MatCheckPreallocated(mat, 1); 2591 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2592 PetscAssertPointer(irow, 3); 2593 PetscAssertPointer(icol, 5); 2594 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2595 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2596 if (PetscDefined(USE_DEBUG)) { 2597 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2598 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); 2599 } 2600 2601 if (mat->assembled) { 2602 mat->was_assembled = PETSC_TRUE; 2603 mat->assembled = PETSC_FALSE; 2604 } 2605 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2606 PetscInt irbs, rbs; 2607 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2608 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2609 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2610 } 2611 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2612 PetscInt icbs, cbs; 2613 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2614 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2615 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2616 } 2617 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2618 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2619 else { 2620 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2621 const PetscInt *irowm, *icolm; 2622 2623 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2624 bufr = buf; 2625 bufc = buf + nrow; 2626 irowm = bufr; 2627 icolm = bufc; 2628 } else { 2629 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2630 irowm = bufr; 2631 icolm = bufc; 2632 } 2633 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2634 else irowm = irow; 2635 if (mat->cmap->mapping) { 2636 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2637 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2638 } else icolm = irowm; 2639 } else icolm = icol; 2640 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2641 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2642 } 2643 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2644 PetscFunctionReturn(PETSC_SUCCESS); 2645 } 2646 2647 /*@ 2648 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2649 2650 Collective 2651 2652 Input Parameters: 2653 + mat - the matrix 2654 - x - the vector to be multiplied 2655 2656 Output Parameter: 2657 . y - the result 2658 2659 Level: developer 2660 2661 Note: 2662 The vectors `x` and `y` cannot be the same. I.e., one cannot 2663 call `MatMultDiagonalBlock`(A,y,y). 2664 2665 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2666 @*/ 2667 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2668 { 2669 PetscFunctionBegin; 2670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2671 PetscValidType(mat, 1); 2672 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2673 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2674 2675 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2676 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2677 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2678 MatCheckPreallocated(mat, 1); 2679 2680 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2681 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2682 PetscFunctionReturn(PETSC_SUCCESS); 2683 } 2684 2685 /*@ 2686 MatMult - Computes the matrix-vector product, $y = Ax$. 2687 2688 Neighbor-wise Collective 2689 2690 Input Parameters: 2691 + mat - the matrix 2692 - x - the vector to be multiplied 2693 2694 Output Parameter: 2695 . y - the result 2696 2697 Level: beginner 2698 2699 Note: 2700 The vectors `x` and `y` cannot be the same. I.e., one cannot 2701 call `MatMult`(A,y,y). 2702 2703 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2704 @*/ 2705 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2706 { 2707 PetscFunctionBegin; 2708 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2709 PetscValidType(mat, 1); 2710 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2711 VecCheckAssembled(x); 2712 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2713 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2714 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2715 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2716 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); 2717 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); 2718 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); 2719 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); 2720 PetscCall(VecSetErrorIfLocked(y, 3)); 2721 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2722 MatCheckPreallocated(mat, 1); 2723 2724 PetscCall(VecLockReadPush(x)); 2725 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2726 PetscUseTypeMethod(mat, mult, x, y); 2727 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2728 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2729 PetscCall(VecLockReadPop(x)); 2730 PetscFunctionReturn(PETSC_SUCCESS); 2731 } 2732 2733 /*@ 2734 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2735 2736 Neighbor-wise Collective 2737 2738 Input Parameters: 2739 + mat - the matrix 2740 - x - the vector to be multiplied 2741 2742 Output Parameter: 2743 . y - the result 2744 2745 Level: beginner 2746 2747 Notes: 2748 The vectors `x` and `y` cannot be the same. I.e., one cannot 2749 call `MatMultTranspose`(A,y,y). 2750 2751 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2752 use `MatMultHermitianTranspose()` 2753 2754 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2755 @*/ 2756 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2757 { 2758 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2759 2760 PetscFunctionBegin; 2761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2762 PetscValidType(mat, 1); 2763 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2764 VecCheckAssembled(x); 2765 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2766 2767 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2768 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2769 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2770 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); 2771 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); 2772 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); 2773 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); 2774 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2775 MatCheckPreallocated(mat, 1); 2776 2777 if (!mat->ops->multtranspose) { 2778 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2779 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); 2780 } else op = mat->ops->multtranspose; 2781 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2782 PetscCall(VecLockReadPush(x)); 2783 PetscCall((*op)(mat, x, y)); 2784 PetscCall(VecLockReadPop(x)); 2785 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2786 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2787 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2788 PetscFunctionReturn(PETSC_SUCCESS); 2789 } 2790 2791 /*@ 2792 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2793 2794 Neighbor-wise Collective 2795 2796 Input Parameters: 2797 + mat - the matrix 2798 - x - the vector to be multiplied 2799 2800 Output Parameter: 2801 . y - the result 2802 2803 Level: beginner 2804 2805 Notes: 2806 The vectors `x` and `y` cannot be the same. I.e., one cannot 2807 call `MatMultHermitianTranspose`(A,y,y). 2808 2809 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2810 2811 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2812 2813 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2814 @*/ 2815 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2816 { 2817 PetscFunctionBegin; 2818 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2819 PetscValidType(mat, 1); 2820 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2821 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2822 2823 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2824 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2825 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2826 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); 2827 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); 2828 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); 2829 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); 2830 MatCheckPreallocated(mat, 1); 2831 2832 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2833 #if defined(PETSC_USE_COMPLEX) 2834 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2835 PetscCall(VecLockReadPush(x)); 2836 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2837 else PetscUseTypeMethod(mat, mult, x, y); 2838 PetscCall(VecLockReadPop(x)); 2839 } else { 2840 Vec w; 2841 PetscCall(VecDuplicate(x, &w)); 2842 PetscCall(VecCopy(x, w)); 2843 PetscCall(VecConjugate(w)); 2844 PetscCall(MatMultTranspose(mat, w, y)); 2845 PetscCall(VecDestroy(&w)); 2846 PetscCall(VecConjugate(y)); 2847 } 2848 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2849 #else 2850 PetscCall(MatMultTranspose(mat, x, y)); 2851 #endif 2852 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2853 PetscFunctionReturn(PETSC_SUCCESS); 2854 } 2855 2856 /*@ 2857 MatMultAdd - Computes $v3 = v2 + A * v1$. 2858 2859 Neighbor-wise Collective 2860 2861 Input Parameters: 2862 + mat - the matrix 2863 . v1 - the vector to be multiplied by `mat` 2864 - v2 - the vector to be added to the result 2865 2866 Output Parameter: 2867 . v3 - the result 2868 2869 Level: beginner 2870 2871 Note: 2872 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2873 call `MatMultAdd`(A,v1,v2,v1). 2874 2875 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2876 @*/ 2877 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2878 { 2879 PetscFunctionBegin; 2880 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2881 PetscValidType(mat, 1); 2882 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2883 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2884 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2885 2886 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2887 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2888 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); 2889 /* 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); 2890 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); */ 2891 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); 2892 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); 2893 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2894 MatCheckPreallocated(mat, 1); 2895 2896 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2897 PetscCall(VecLockReadPush(v1)); 2898 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2899 PetscCall(VecLockReadPop(v1)); 2900 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2901 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2902 PetscFunctionReturn(PETSC_SUCCESS); 2903 } 2904 2905 /*@ 2906 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2907 2908 Neighbor-wise Collective 2909 2910 Input Parameters: 2911 + mat - the matrix 2912 . v1 - the vector to be multiplied by the transpose of the matrix 2913 - v2 - the vector to be added to the result 2914 2915 Output Parameter: 2916 . v3 - the result 2917 2918 Level: beginner 2919 2920 Note: 2921 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2922 call `MatMultTransposeAdd`(A,v1,v2,v1). 2923 2924 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2925 @*/ 2926 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2927 { 2928 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2929 2930 PetscFunctionBegin; 2931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2932 PetscValidType(mat, 1); 2933 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2934 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2935 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2936 2937 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2938 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2939 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); 2940 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); 2941 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); 2942 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2943 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2944 MatCheckPreallocated(mat, 1); 2945 2946 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2947 PetscCall(VecLockReadPush(v1)); 2948 PetscCall((*op)(mat, v1, v2, v3)); 2949 PetscCall(VecLockReadPop(v1)); 2950 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2951 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2952 PetscFunctionReturn(PETSC_SUCCESS); 2953 } 2954 2955 /*@ 2956 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2957 2958 Neighbor-wise Collective 2959 2960 Input Parameters: 2961 + mat - the matrix 2962 . v1 - the vector to be multiplied by the Hermitian transpose 2963 - v2 - the vector to be added to the result 2964 2965 Output Parameter: 2966 . v3 - the result 2967 2968 Level: beginner 2969 2970 Note: 2971 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2972 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2973 2974 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2975 @*/ 2976 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2977 { 2978 PetscFunctionBegin; 2979 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2980 PetscValidType(mat, 1); 2981 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2982 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2983 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2984 2985 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2986 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2987 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2988 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); 2989 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); 2990 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); 2991 MatCheckPreallocated(mat, 1); 2992 2993 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2994 PetscCall(VecLockReadPush(v1)); 2995 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2996 else { 2997 Vec w, z; 2998 PetscCall(VecDuplicate(v1, &w)); 2999 PetscCall(VecCopy(v1, w)); 3000 PetscCall(VecConjugate(w)); 3001 PetscCall(VecDuplicate(v3, &z)); 3002 PetscCall(MatMultTranspose(mat, w, z)); 3003 PetscCall(VecDestroy(&w)); 3004 PetscCall(VecConjugate(z)); 3005 if (v2 != v3) { 3006 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 3007 } else { 3008 PetscCall(VecAXPY(v3, 1.0, z)); 3009 } 3010 PetscCall(VecDestroy(&z)); 3011 } 3012 PetscCall(VecLockReadPop(v1)); 3013 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 3014 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 3015 PetscFunctionReturn(PETSC_SUCCESS); 3016 } 3017 3018 /*@ 3019 MatGetFactorType - gets the type of factorization a matrix is 3020 3021 Not Collective 3022 3023 Input Parameter: 3024 . mat - the matrix 3025 3026 Output Parameter: 3027 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3028 3029 Level: intermediate 3030 3031 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3032 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3033 @*/ 3034 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3035 { 3036 PetscFunctionBegin; 3037 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3038 PetscValidType(mat, 1); 3039 PetscAssertPointer(t, 2); 3040 *t = mat->factortype; 3041 PetscFunctionReturn(PETSC_SUCCESS); 3042 } 3043 3044 /*@ 3045 MatSetFactorType - sets the type of factorization a matrix is 3046 3047 Logically Collective 3048 3049 Input Parameters: 3050 + mat - the matrix 3051 - 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` 3052 3053 Level: intermediate 3054 3055 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3056 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3057 @*/ 3058 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3059 { 3060 PetscFunctionBegin; 3061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3062 PetscValidType(mat, 1); 3063 mat->factortype = t; 3064 PetscFunctionReturn(PETSC_SUCCESS); 3065 } 3066 3067 /*@ 3068 MatGetInfo - Returns information about matrix storage (number of 3069 nonzeros, memory, etc.). 3070 3071 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3072 3073 Input Parameters: 3074 + mat - the matrix 3075 - 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) 3076 3077 Output Parameter: 3078 . info - matrix information context 3079 3080 Options Database Key: 3081 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3082 3083 Level: intermediate 3084 3085 Notes: 3086 The `MatInfo` context contains a variety of matrix data, including 3087 number of nonzeros allocated and used, number of mallocs during 3088 matrix assembly, etc. Additional information for factored matrices 3089 is provided (such as the fill ratio, number of mallocs during 3090 factorization, etc.). 3091 3092 Example: 3093 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3094 data within the `MatInfo` context. For example, 3095 .vb 3096 MatInfo info; 3097 Mat A; 3098 double mal, nz_a, nz_u; 3099 3100 MatGetInfo(A, MAT_LOCAL, &info); 3101 mal = info.mallocs; 3102 nz_a = info.nz_allocated; 3103 .ve 3104 3105 Fortran Note: 3106 Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters 3107 of interest. See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h 3108 a complete list of parameter names. 3109 .vb 3110 MatInfo info(MAT_INFO_SIZE) 3111 double precision mal, nz_a 3112 Mat A 3113 integer ierr 3114 3115 call MatGetInfo(A, MAT_LOCAL, info, ierr) 3116 mal = info(MAT_INFO_MALLOCS) 3117 nz_a = info(MAT_INFO_NZ_ALLOCATED) 3118 .ve 3119 3120 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3121 @*/ 3122 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3123 { 3124 PetscFunctionBegin; 3125 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3126 PetscValidType(mat, 1); 3127 PetscAssertPointer(info, 3); 3128 MatCheckPreallocated(mat, 1); 3129 PetscUseTypeMethod(mat, getinfo, flag, info); 3130 PetscFunctionReturn(PETSC_SUCCESS); 3131 } 3132 3133 /* 3134 This is used by external packages where it is not easy to get the info from the actual 3135 matrix factorization. 3136 */ 3137 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3138 { 3139 PetscFunctionBegin; 3140 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3141 PetscFunctionReturn(PETSC_SUCCESS); 3142 } 3143 3144 /*@ 3145 MatLUFactor - Performs in-place LU factorization of matrix. 3146 3147 Collective 3148 3149 Input Parameters: 3150 + mat - the matrix 3151 . row - row permutation 3152 . col - column permutation 3153 - info - options for factorization, includes 3154 .vb 3155 fill - expected fill as ratio of original fill. 3156 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3157 Run with the option -info to determine an optimal value to use 3158 .ve 3159 3160 Level: developer 3161 3162 Notes: 3163 Most users should employ the `KSP` interface for linear solvers 3164 instead of working directly with matrix algebra routines such as this. 3165 See, e.g., `KSPCreate()`. 3166 3167 This changes the state of the matrix to a factored matrix; it cannot be used 3168 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3169 3170 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3171 when not using `KSP`. 3172 3173 Developer Note: 3174 The Fortran interface is not autogenerated as the 3175 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3176 3177 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3178 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3179 @*/ 3180 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3181 { 3182 MatFactorInfo tinfo; 3183 3184 PetscFunctionBegin; 3185 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3186 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3187 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3188 if (info) PetscAssertPointer(info, 4); 3189 PetscValidType(mat, 1); 3190 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3191 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3192 MatCheckPreallocated(mat, 1); 3193 if (!info) { 3194 PetscCall(MatFactorInfoInitialize(&tinfo)); 3195 info = &tinfo; 3196 } 3197 3198 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3199 PetscUseTypeMethod(mat, lufactor, row, col, info); 3200 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3201 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3202 PetscFunctionReturn(PETSC_SUCCESS); 3203 } 3204 3205 /*@ 3206 MatILUFactor - Performs in-place ILU factorization of matrix. 3207 3208 Collective 3209 3210 Input Parameters: 3211 + mat - the matrix 3212 . row - row permutation 3213 . col - column permutation 3214 - info - structure containing 3215 .vb 3216 levels - number of levels of fill. 3217 expected fill - as ratio of original fill. 3218 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3219 missing diagonal entries) 3220 .ve 3221 3222 Level: developer 3223 3224 Notes: 3225 Most users should employ the `KSP` interface for linear solvers 3226 instead of working directly with matrix algebra routines such as this. 3227 See, e.g., `KSPCreate()`. 3228 3229 Probably really in-place only when level of fill is zero, otherwise allocates 3230 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3231 when not using `KSP`. 3232 3233 Developer Note: 3234 The Fortran interface is not autogenerated as the 3235 interface definition cannot be generated correctly [due to MatFactorInfo] 3236 3237 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3238 @*/ 3239 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3240 { 3241 PetscFunctionBegin; 3242 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3243 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3244 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3245 PetscAssertPointer(info, 4); 3246 PetscValidType(mat, 1); 3247 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3248 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3249 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3250 MatCheckPreallocated(mat, 1); 3251 3252 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3253 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3254 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3255 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3256 PetscFunctionReturn(PETSC_SUCCESS); 3257 } 3258 3259 /*@ 3260 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3261 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3262 3263 Collective 3264 3265 Input Parameters: 3266 + fact - the factor matrix obtained with `MatGetFactor()` 3267 . mat - the matrix 3268 . row - the row permutation 3269 . col - the column permutation 3270 - info - options for factorization, includes 3271 .vb 3272 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3273 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3274 .ve 3275 3276 Level: developer 3277 3278 Notes: 3279 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3280 3281 Most users should employ the simplified `KSP` interface for linear solvers 3282 instead of working directly with matrix algebra routines such as this. 3283 See, e.g., `KSPCreate()`. 3284 3285 Developer Note: 3286 The Fortran interface is not autogenerated as the 3287 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3288 3289 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3290 @*/ 3291 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3292 { 3293 MatFactorInfo tinfo; 3294 3295 PetscFunctionBegin; 3296 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3297 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3298 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3299 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3300 if (info) PetscAssertPointer(info, 5); 3301 PetscValidType(fact, 1); 3302 PetscValidType(mat, 2); 3303 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3304 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3305 MatCheckPreallocated(mat, 2); 3306 if (!info) { 3307 PetscCall(MatFactorInfoInitialize(&tinfo)); 3308 info = &tinfo; 3309 } 3310 3311 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3312 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3313 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3314 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3315 PetscFunctionReturn(PETSC_SUCCESS); 3316 } 3317 3318 /*@ 3319 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3320 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3321 3322 Collective 3323 3324 Input Parameters: 3325 + fact - the factor matrix obtained with `MatGetFactor()` 3326 . mat - the matrix 3327 - info - options for factorization 3328 3329 Level: developer 3330 3331 Notes: 3332 See `MatLUFactor()` for in-place factorization. See 3333 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3334 3335 Most users should employ the `KSP` interface for linear solvers 3336 instead of working directly with matrix algebra routines such as this. 3337 See, e.g., `KSPCreate()`. 3338 3339 Developer Note: 3340 The Fortran interface is not autogenerated as the 3341 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3342 3343 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3344 @*/ 3345 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3346 { 3347 MatFactorInfo tinfo; 3348 3349 PetscFunctionBegin; 3350 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3352 PetscValidType(fact, 1); 3353 PetscValidType(mat, 2); 3354 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3355 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, 3356 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3357 3358 MatCheckPreallocated(mat, 2); 3359 if (!info) { 3360 PetscCall(MatFactorInfoInitialize(&tinfo)); 3361 info = &tinfo; 3362 } 3363 3364 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3365 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3366 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3367 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3368 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3369 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3370 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3371 PetscFunctionReturn(PETSC_SUCCESS); 3372 } 3373 3374 /*@ 3375 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3376 symmetric matrix. 3377 3378 Collective 3379 3380 Input Parameters: 3381 + mat - the matrix 3382 . perm - row and column permutations 3383 - info - expected fill as ratio of original fill 3384 3385 Level: developer 3386 3387 Notes: 3388 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3389 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3390 3391 Most users should employ the `KSP` interface for linear solvers 3392 instead of working directly with matrix algebra routines such as this. 3393 See, e.g., `KSPCreate()`. 3394 3395 Developer Note: 3396 The Fortran interface is not autogenerated as the 3397 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3398 3399 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3400 `MatGetOrdering()` 3401 @*/ 3402 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3403 { 3404 MatFactorInfo tinfo; 3405 3406 PetscFunctionBegin; 3407 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3408 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3409 if (info) PetscAssertPointer(info, 3); 3410 PetscValidType(mat, 1); 3411 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3412 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3413 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3414 MatCheckPreallocated(mat, 1); 3415 if (!info) { 3416 PetscCall(MatFactorInfoInitialize(&tinfo)); 3417 info = &tinfo; 3418 } 3419 3420 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3421 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3422 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3423 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3424 PetscFunctionReturn(PETSC_SUCCESS); 3425 } 3426 3427 /*@ 3428 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3429 of a symmetric matrix. 3430 3431 Collective 3432 3433 Input Parameters: 3434 + fact - the factor matrix obtained with `MatGetFactor()` 3435 . mat - the matrix 3436 . perm - row and column permutations 3437 - info - options for factorization, includes 3438 .vb 3439 fill - expected fill as ratio of original fill. 3440 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3441 Run with the option -info to determine an optimal value to use 3442 .ve 3443 3444 Level: developer 3445 3446 Notes: 3447 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3448 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3449 3450 Most users should employ the `KSP` interface for linear solvers 3451 instead of working directly with matrix algebra routines such as this. 3452 See, e.g., `KSPCreate()`. 3453 3454 Developer Note: 3455 The Fortran interface is not autogenerated as the 3456 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3457 3458 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3459 `MatGetOrdering()` 3460 @*/ 3461 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3462 { 3463 MatFactorInfo tinfo; 3464 3465 PetscFunctionBegin; 3466 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3467 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3468 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3469 if (info) PetscAssertPointer(info, 4); 3470 PetscValidType(fact, 1); 3471 PetscValidType(mat, 2); 3472 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3473 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3474 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3475 MatCheckPreallocated(mat, 2); 3476 if (!info) { 3477 PetscCall(MatFactorInfoInitialize(&tinfo)); 3478 info = &tinfo; 3479 } 3480 3481 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3482 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3483 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3484 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3485 PetscFunctionReturn(PETSC_SUCCESS); 3486 } 3487 3488 /*@ 3489 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3490 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3491 `MatCholeskyFactorSymbolic()`. 3492 3493 Collective 3494 3495 Input Parameters: 3496 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3497 . mat - the initial matrix that is to be factored 3498 - info - options for factorization 3499 3500 Level: developer 3501 3502 Note: 3503 Most users should employ the `KSP` interface for linear solvers 3504 instead of working directly with matrix algebra routines such as this. 3505 See, e.g., `KSPCreate()`. 3506 3507 Developer Note: 3508 The Fortran interface is not autogenerated as the 3509 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3510 3511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3512 @*/ 3513 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3514 { 3515 MatFactorInfo tinfo; 3516 3517 PetscFunctionBegin; 3518 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3519 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3520 PetscValidType(fact, 1); 3521 PetscValidType(mat, 2); 3522 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3523 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, 3524 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3525 MatCheckPreallocated(mat, 2); 3526 if (!info) { 3527 PetscCall(MatFactorInfoInitialize(&tinfo)); 3528 info = &tinfo; 3529 } 3530 3531 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3532 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3533 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3534 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3535 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3536 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3537 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3538 PetscFunctionReturn(PETSC_SUCCESS); 3539 } 3540 3541 /*@ 3542 MatQRFactor - Performs in-place QR factorization of matrix. 3543 3544 Collective 3545 3546 Input Parameters: 3547 + mat - the matrix 3548 . col - column permutation 3549 - info - options for factorization, includes 3550 .vb 3551 fill - expected fill as ratio of original fill. 3552 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3553 Run with the option -info to determine an optimal value to use 3554 .ve 3555 3556 Level: developer 3557 3558 Notes: 3559 Most users should employ the `KSP` interface for linear solvers 3560 instead of working directly with matrix algebra routines such as this. 3561 See, e.g., `KSPCreate()`. 3562 3563 This changes the state of the matrix to a factored matrix; it cannot be used 3564 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3565 3566 Developer Note: 3567 The Fortran interface is not autogenerated as the 3568 interface definition cannot be generated correctly [due to MatFactorInfo] 3569 3570 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3571 `MatSetUnfactored()` 3572 @*/ 3573 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3574 { 3575 PetscFunctionBegin; 3576 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3577 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3578 if (info) PetscAssertPointer(info, 3); 3579 PetscValidType(mat, 1); 3580 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3581 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3582 MatCheckPreallocated(mat, 1); 3583 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3584 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3585 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3586 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3587 PetscFunctionReturn(PETSC_SUCCESS); 3588 } 3589 3590 /*@ 3591 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3592 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3593 3594 Collective 3595 3596 Input Parameters: 3597 + fact - the factor matrix obtained with `MatGetFactor()` 3598 . mat - the matrix 3599 . col - column permutation 3600 - info - options for factorization, includes 3601 .vb 3602 fill - expected fill as ratio of original fill. 3603 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3604 Run with the option -info to determine an optimal value to use 3605 .ve 3606 3607 Level: developer 3608 3609 Note: 3610 Most users should employ the `KSP` interface for linear solvers 3611 instead of working directly with matrix algebra routines such as this. 3612 See, e.g., `KSPCreate()`. 3613 3614 Developer Note: 3615 The Fortran interface is not autogenerated as the 3616 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3617 3618 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3619 @*/ 3620 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3621 { 3622 MatFactorInfo tinfo; 3623 3624 PetscFunctionBegin; 3625 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3627 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3628 if (info) PetscAssertPointer(info, 4); 3629 PetscValidType(fact, 1); 3630 PetscValidType(mat, 2); 3631 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3632 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3633 MatCheckPreallocated(mat, 2); 3634 if (!info) { 3635 PetscCall(MatFactorInfoInitialize(&tinfo)); 3636 info = &tinfo; 3637 } 3638 3639 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3640 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3641 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3642 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3643 PetscFunctionReturn(PETSC_SUCCESS); 3644 } 3645 3646 /*@ 3647 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3648 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3649 3650 Collective 3651 3652 Input Parameters: 3653 + fact - the factor matrix obtained with `MatGetFactor()` 3654 . mat - the matrix 3655 - info - options for factorization 3656 3657 Level: developer 3658 3659 Notes: 3660 See `MatQRFactor()` for in-place factorization. 3661 3662 Most users should employ the `KSP` interface for linear solvers 3663 instead of working directly with matrix algebra routines such as this. 3664 See, e.g., `KSPCreate()`. 3665 3666 Developer Note: 3667 The Fortran interface is not autogenerated as the 3668 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3669 3670 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3671 @*/ 3672 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3673 { 3674 MatFactorInfo tinfo; 3675 3676 PetscFunctionBegin; 3677 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3678 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3679 PetscValidType(fact, 1); 3680 PetscValidType(mat, 2); 3681 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3682 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, 3683 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3684 3685 MatCheckPreallocated(mat, 2); 3686 if (!info) { 3687 PetscCall(MatFactorInfoInitialize(&tinfo)); 3688 info = &tinfo; 3689 } 3690 3691 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3692 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3693 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3694 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3695 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3696 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3697 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3698 PetscFunctionReturn(PETSC_SUCCESS); 3699 } 3700 3701 /*@ 3702 MatSolve - Solves $A x = b$, given a factored matrix. 3703 3704 Neighbor-wise Collective 3705 3706 Input Parameters: 3707 + mat - the factored matrix 3708 - b - the right-hand-side vector 3709 3710 Output Parameter: 3711 . x - the result vector 3712 3713 Level: developer 3714 3715 Notes: 3716 The vectors `b` and `x` cannot be the same. I.e., one cannot 3717 call `MatSolve`(A,x,x). 3718 3719 Most users should employ the `KSP` interface for linear solvers 3720 instead of working directly with matrix algebra routines such as this. 3721 See, e.g., `KSPCreate()`. 3722 3723 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3724 @*/ 3725 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3726 { 3727 PetscFunctionBegin; 3728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3729 PetscValidType(mat, 1); 3730 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3731 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3732 PetscCheckSameComm(mat, 1, b, 2); 3733 PetscCheckSameComm(mat, 1, x, 3); 3734 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3735 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); 3736 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); 3737 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); 3738 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3739 MatCheckPreallocated(mat, 1); 3740 3741 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3742 PetscCall(VecFlag(x, mat->factorerrortype)); 3743 if (mat->factorerrortype) { 3744 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3745 } else PetscUseTypeMethod(mat, solve, b, x); 3746 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3747 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3748 PetscFunctionReturn(PETSC_SUCCESS); 3749 } 3750 3751 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3752 { 3753 Vec b, x; 3754 PetscInt N, i; 3755 PetscErrorCode (*f)(Mat, Vec, Vec); 3756 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3757 3758 PetscFunctionBegin; 3759 if (A->factorerrortype) { 3760 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3761 PetscCall(MatSetInf(X)); 3762 PetscFunctionReturn(PETSC_SUCCESS); 3763 } 3764 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3765 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3766 PetscCall(MatBoundToCPU(A, &Abound)); 3767 if (!Abound) { 3768 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3769 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3770 } 3771 #if PetscDefined(HAVE_CUDA) 3772 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3773 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3774 #elif PetscDefined(HAVE_HIP) 3775 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3776 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3777 #endif 3778 PetscCall(MatGetSize(B, NULL, &N)); 3779 for (i = 0; i < N; i++) { 3780 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3781 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3782 PetscCall((*f)(A, b, x)); 3783 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3784 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3785 } 3786 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3787 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3788 PetscFunctionReturn(PETSC_SUCCESS); 3789 } 3790 3791 /*@ 3792 MatMatSolve - Solves $A X = B$, given a factored matrix. 3793 3794 Neighbor-wise Collective 3795 3796 Input Parameters: 3797 + A - the factored matrix 3798 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3799 3800 Output Parameter: 3801 . X - the result matrix (dense matrix) 3802 3803 Level: developer 3804 3805 Note: 3806 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3807 otherwise, `B` and `X` cannot be the same. 3808 3809 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3810 @*/ 3811 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3812 { 3813 PetscFunctionBegin; 3814 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3815 PetscValidType(A, 1); 3816 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3817 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3818 PetscCheckSameComm(A, 1, B, 2); 3819 PetscCheckSameComm(A, 1, X, 3); 3820 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); 3821 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); 3822 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"); 3823 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3824 MatCheckPreallocated(A, 1); 3825 3826 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3827 if (!A->ops->matsolve) { 3828 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3829 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3830 } else PetscUseTypeMethod(A, matsolve, B, X); 3831 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3832 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3833 PetscFunctionReturn(PETSC_SUCCESS); 3834 } 3835 3836 /*@ 3837 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3838 3839 Neighbor-wise Collective 3840 3841 Input Parameters: 3842 + A - the factored matrix 3843 - B - the right-hand-side matrix (`MATDENSE` matrix) 3844 3845 Output Parameter: 3846 . X - the result matrix (dense matrix) 3847 3848 Level: developer 3849 3850 Note: 3851 The matrices `B` and `X` cannot be the same. I.e., one cannot 3852 call `MatMatSolveTranspose`(A,X,X). 3853 3854 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3855 @*/ 3856 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3857 { 3858 PetscFunctionBegin; 3859 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3860 PetscValidType(A, 1); 3861 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3862 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3863 PetscCheckSameComm(A, 1, B, 2); 3864 PetscCheckSameComm(A, 1, X, 3); 3865 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3866 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); 3867 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); 3868 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); 3869 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"); 3870 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3871 MatCheckPreallocated(A, 1); 3872 3873 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3874 if (!A->ops->matsolvetranspose) { 3875 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3876 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3877 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3878 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3879 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3880 PetscFunctionReturn(PETSC_SUCCESS); 3881 } 3882 3883 /*@ 3884 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3885 3886 Neighbor-wise Collective 3887 3888 Input Parameters: 3889 + A - the factored matrix 3890 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3891 3892 Output Parameter: 3893 . X - the result matrix (dense matrix) 3894 3895 Level: developer 3896 3897 Note: 3898 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 3899 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3900 3901 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3902 @*/ 3903 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3904 { 3905 PetscFunctionBegin; 3906 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3907 PetscValidType(A, 1); 3908 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3909 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3910 PetscCheckSameComm(A, 1, Bt, 2); 3911 PetscCheckSameComm(A, 1, X, 3); 3912 3913 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3914 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); 3915 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); 3916 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"); 3917 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3918 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3919 MatCheckPreallocated(A, 1); 3920 3921 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3922 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3923 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3924 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3925 PetscFunctionReturn(PETSC_SUCCESS); 3926 } 3927 3928 /*@ 3929 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3930 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3931 3932 Neighbor-wise Collective 3933 3934 Input Parameters: 3935 + mat - the factored matrix 3936 - b - the right-hand-side vector 3937 3938 Output Parameter: 3939 . x - the result vector 3940 3941 Level: developer 3942 3943 Notes: 3944 `MatSolve()` should be used for most applications, as it performs 3945 a forward solve followed by a backward solve. 3946 3947 The vectors `b` and `x` cannot be the same, i.e., one cannot 3948 call `MatForwardSolve`(A,x,x). 3949 3950 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3951 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3952 `MatForwardSolve()` solves $U^T*D y = b$, and 3953 `MatBackwardSolve()` solves $U x = y$. 3954 Thus they do not provide a symmetric preconditioner. 3955 3956 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3957 @*/ 3958 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3959 { 3960 PetscFunctionBegin; 3961 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3962 PetscValidType(mat, 1); 3963 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3964 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3965 PetscCheckSameComm(mat, 1, b, 2); 3966 PetscCheckSameComm(mat, 1, x, 3); 3967 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3968 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); 3969 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); 3970 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); 3971 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3972 MatCheckPreallocated(mat, 1); 3973 3974 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3975 PetscUseTypeMethod(mat, forwardsolve, b, x); 3976 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3977 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3978 PetscFunctionReturn(PETSC_SUCCESS); 3979 } 3980 3981 /*@ 3982 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3983 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3984 3985 Neighbor-wise Collective 3986 3987 Input Parameters: 3988 + mat - the factored matrix 3989 - b - the right-hand-side vector 3990 3991 Output Parameter: 3992 . x - the result vector 3993 3994 Level: developer 3995 3996 Notes: 3997 `MatSolve()` should be used for most applications, as it performs 3998 a forward solve followed by a backward solve. 3999 4000 The vectors `b` and `x` cannot be the same. I.e., one cannot 4001 call `MatBackwardSolve`(A,x,x). 4002 4003 For matrix in `MATSEQBAIJ` format with block size larger than 1, 4004 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 4005 `MatForwardSolve()` solves $U^T*D y = b$, and 4006 `MatBackwardSolve()` solves $U x = y$. 4007 Thus they do not provide a symmetric preconditioner. 4008 4009 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 4010 @*/ 4011 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 4012 { 4013 PetscFunctionBegin; 4014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4015 PetscValidType(mat, 1); 4016 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4017 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4018 PetscCheckSameComm(mat, 1, b, 2); 4019 PetscCheckSameComm(mat, 1, x, 3); 4020 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4021 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); 4022 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); 4023 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); 4024 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4025 MatCheckPreallocated(mat, 1); 4026 4027 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 4028 PetscUseTypeMethod(mat, backwardsolve, b, x); 4029 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 4030 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4031 PetscFunctionReturn(PETSC_SUCCESS); 4032 } 4033 4034 /*@ 4035 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 4036 4037 Neighbor-wise Collective 4038 4039 Input Parameters: 4040 + mat - the factored matrix 4041 . b - the right-hand-side vector 4042 - y - the vector to be added to 4043 4044 Output Parameter: 4045 . x - the result vector 4046 4047 Level: developer 4048 4049 Note: 4050 The vectors `b` and `x` cannot be the same. I.e., one cannot 4051 call `MatSolveAdd`(A,x,y,x). 4052 4053 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4054 @*/ 4055 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4056 { 4057 PetscScalar one = 1.0; 4058 Vec tmp; 4059 4060 PetscFunctionBegin; 4061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4062 PetscValidType(mat, 1); 4063 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4064 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4065 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4066 PetscCheckSameComm(mat, 1, b, 2); 4067 PetscCheckSameComm(mat, 1, y, 3); 4068 PetscCheckSameComm(mat, 1, x, 4); 4069 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4070 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); 4071 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); 4072 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); 4073 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); 4074 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); 4075 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4076 MatCheckPreallocated(mat, 1); 4077 4078 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4079 PetscCall(VecFlag(x, mat->factorerrortype)); 4080 if (mat->factorerrortype) { 4081 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4082 } else if (mat->ops->solveadd) { 4083 PetscUseTypeMethod(mat, solveadd, b, y, x); 4084 } else { 4085 /* do the solve then the add manually */ 4086 if (x != y) { 4087 PetscCall(MatSolve(mat, b, x)); 4088 PetscCall(VecAXPY(x, one, y)); 4089 } else { 4090 PetscCall(VecDuplicate(x, &tmp)); 4091 PetscCall(VecCopy(x, tmp)); 4092 PetscCall(MatSolve(mat, b, x)); 4093 PetscCall(VecAXPY(x, one, tmp)); 4094 PetscCall(VecDestroy(&tmp)); 4095 } 4096 } 4097 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4098 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4099 PetscFunctionReturn(PETSC_SUCCESS); 4100 } 4101 4102 /*@ 4103 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4104 4105 Neighbor-wise Collective 4106 4107 Input Parameters: 4108 + mat - the factored matrix 4109 - b - the right-hand-side vector 4110 4111 Output Parameter: 4112 . x - the result vector 4113 4114 Level: developer 4115 4116 Notes: 4117 The vectors `b` and `x` cannot be the same. I.e., one cannot 4118 call `MatSolveTranspose`(A,x,x). 4119 4120 Most users should employ the `KSP` interface for linear solvers 4121 instead of working directly with matrix algebra routines such as this. 4122 See, e.g., `KSPCreate()`. 4123 4124 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4125 @*/ 4126 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4127 { 4128 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4129 4130 PetscFunctionBegin; 4131 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4132 PetscValidType(mat, 1); 4133 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4134 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4135 PetscCheckSameComm(mat, 1, b, 2); 4136 PetscCheckSameComm(mat, 1, x, 3); 4137 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4138 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); 4139 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); 4140 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4141 MatCheckPreallocated(mat, 1); 4142 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4143 PetscCall(VecFlag(x, mat->factorerrortype)); 4144 if (mat->factorerrortype) { 4145 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4146 } else { 4147 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4148 PetscCall((*f)(mat, b, x)); 4149 } 4150 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4151 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4152 PetscFunctionReturn(PETSC_SUCCESS); 4153 } 4154 4155 /*@ 4156 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4157 factored matrix. 4158 4159 Neighbor-wise Collective 4160 4161 Input Parameters: 4162 + mat - the factored matrix 4163 . b - the right-hand-side vector 4164 - y - the vector to be added to 4165 4166 Output Parameter: 4167 . x - the result vector 4168 4169 Level: developer 4170 4171 Note: 4172 The vectors `b` and `x` cannot be the same. I.e., one cannot 4173 call `MatSolveTransposeAdd`(A,x,y,x). 4174 4175 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4176 @*/ 4177 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4178 { 4179 PetscScalar one = 1.0; 4180 Vec tmp; 4181 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4182 4183 PetscFunctionBegin; 4184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4185 PetscValidType(mat, 1); 4186 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4187 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4188 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4189 PetscCheckSameComm(mat, 1, b, 2); 4190 PetscCheckSameComm(mat, 1, y, 3); 4191 PetscCheckSameComm(mat, 1, x, 4); 4192 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4193 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); 4194 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); 4195 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); 4196 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); 4197 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4198 MatCheckPreallocated(mat, 1); 4199 4200 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4201 PetscCall(VecFlag(x, mat->factorerrortype)); 4202 if (mat->factorerrortype) { 4203 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4204 } else if (f) { 4205 PetscCall((*f)(mat, b, y, x)); 4206 } else { 4207 /* do the solve then the add manually */ 4208 if (x != y) { 4209 PetscCall(MatSolveTranspose(mat, b, x)); 4210 PetscCall(VecAXPY(x, one, y)); 4211 } else { 4212 PetscCall(VecDuplicate(x, &tmp)); 4213 PetscCall(VecCopy(x, tmp)); 4214 PetscCall(MatSolveTranspose(mat, b, x)); 4215 PetscCall(VecAXPY(x, one, tmp)); 4216 PetscCall(VecDestroy(&tmp)); 4217 } 4218 } 4219 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4220 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4221 PetscFunctionReturn(PETSC_SUCCESS); 4222 } 4223 4224 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4225 /*@ 4226 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4227 4228 Neighbor-wise Collective 4229 4230 Input Parameters: 4231 + mat - the matrix 4232 . b - the right-hand side 4233 . omega - the relaxation factor 4234 . flag - flag indicating the type of SOR (see below) 4235 . shift - diagonal shift 4236 . its - the number of iterations 4237 - lits - the number of local iterations 4238 4239 Output Parameter: 4240 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4241 4242 SOR Flags: 4243 + `SOR_FORWARD_SWEEP` - forward SOR 4244 . `SOR_BACKWARD_SWEEP` - backward SOR 4245 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4246 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4247 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4248 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4249 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4250 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4251 upper/lower triangular part of matrix to 4252 vector (with omega) 4253 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4254 4255 Level: developer 4256 4257 Notes: 4258 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4259 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4260 on each processor. 4261 4262 Application programmers will not generally use `MatSOR()` directly, 4263 but instead will employ the `KSP`/`PC` interface. 4264 4265 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4266 4267 Most users should employ the `KSP` interface for linear solvers 4268 instead of working directly with matrix algebra routines such as this. 4269 See, e.g., `KSPCreate()`. 4270 4271 Vectors `x` and `b` CANNOT be the same 4272 4273 The flags are implemented as bitwise inclusive or operations. 4274 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4275 to specify a zero initial guess for SSOR. 4276 4277 Developer Note: 4278 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4279 4280 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4281 @*/ 4282 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4283 { 4284 PetscFunctionBegin; 4285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4286 PetscValidType(mat, 1); 4287 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4288 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4289 PetscCheckSameComm(mat, 1, b, 2); 4290 PetscCheckSameComm(mat, 1, x, 8); 4291 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4292 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4293 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); 4294 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); 4295 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); 4296 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4297 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4298 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4299 4300 MatCheckPreallocated(mat, 1); 4301 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4302 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4303 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4304 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4305 PetscFunctionReturn(PETSC_SUCCESS); 4306 } 4307 4308 /* 4309 Default matrix copy routine. 4310 */ 4311 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4312 { 4313 PetscInt i, rstart = 0, rend = 0, nz; 4314 const PetscInt *cwork; 4315 const PetscScalar *vwork; 4316 4317 PetscFunctionBegin; 4318 if (B->assembled) PetscCall(MatZeroEntries(B)); 4319 if (str == SAME_NONZERO_PATTERN) { 4320 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4321 for (i = rstart; i < rend; i++) { 4322 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4323 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4324 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4325 } 4326 } else { 4327 PetscCall(MatAYPX(B, 0.0, A, str)); 4328 } 4329 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4330 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4331 PetscFunctionReturn(PETSC_SUCCESS); 4332 } 4333 4334 /*@ 4335 MatCopy - Copies a matrix to another matrix. 4336 4337 Collective 4338 4339 Input Parameters: 4340 + A - the matrix 4341 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4342 4343 Output Parameter: 4344 . B - where the copy is put 4345 4346 Level: intermediate 4347 4348 Notes: 4349 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4350 4351 `MatCopy()` copies the matrix entries of a matrix to another existing 4352 matrix (after first zeroing the second matrix). A related routine is 4353 `MatConvert()`, which first creates a new matrix and then copies the data. 4354 4355 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4356 @*/ 4357 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4358 { 4359 PetscInt i; 4360 4361 PetscFunctionBegin; 4362 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4363 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4364 PetscValidType(A, 1); 4365 PetscValidType(B, 2); 4366 PetscCheckSameComm(A, 1, B, 2); 4367 MatCheckPreallocated(B, 2); 4368 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4369 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4370 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, 4371 A->cmap->N, B->cmap->N); 4372 MatCheckPreallocated(A, 1); 4373 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4374 4375 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4376 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4377 else PetscCall(MatCopy_Basic(A, B, str)); 4378 4379 B->stencil.dim = A->stencil.dim; 4380 B->stencil.noc = A->stencil.noc; 4381 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4382 B->stencil.dims[i] = A->stencil.dims[i]; 4383 B->stencil.starts[i] = A->stencil.starts[i]; 4384 } 4385 4386 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4387 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4388 PetscFunctionReturn(PETSC_SUCCESS); 4389 } 4390 4391 /*@ 4392 MatConvert - Converts a matrix to another matrix, either of the same 4393 or different type. 4394 4395 Collective 4396 4397 Input Parameters: 4398 + mat - the matrix 4399 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4400 same type as the original matrix. 4401 - reuse - denotes if the destination matrix is to be created or reused. 4402 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 4403 `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). 4404 4405 Output Parameter: 4406 . M - pointer to place new matrix 4407 4408 Level: intermediate 4409 4410 Notes: 4411 `MatConvert()` first creates a new matrix and then copies the data from 4412 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4413 entries of one matrix to another already existing matrix context. 4414 4415 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4416 the MPI communicator of the generated matrix is always the same as the communicator 4417 of the input matrix. 4418 4419 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4420 @*/ 4421 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4422 { 4423 PetscBool sametype, issame, flg; 4424 PetscBool3 issymmetric, ishermitian; 4425 char convname[256], mtype[256]; 4426 Mat B; 4427 4428 PetscFunctionBegin; 4429 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4430 PetscValidType(mat, 1); 4431 PetscAssertPointer(M, 4); 4432 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4433 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4434 MatCheckPreallocated(mat, 1); 4435 4436 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4437 if (flg) newtype = mtype; 4438 4439 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4440 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4441 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4442 if (reuse == MAT_REUSE_MATRIX) { 4443 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4444 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4445 } 4446 4447 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4448 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4449 PetscFunctionReturn(PETSC_SUCCESS); 4450 } 4451 4452 /* Cache Mat options because some converters use MatHeaderReplace */ 4453 issymmetric = mat->symmetric; 4454 ishermitian = mat->hermitian; 4455 4456 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4457 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4458 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4459 } else { 4460 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4461 const char *prefix[3] = {"seq", "mpi", ""}; 4462 PetscInt i; 4463 /* 4464 Order of precedence: 4465 0) See if newtype is a superclass of the current matrix. 4466 1) See if a specialized converter is known to the current matrix. 4467 2) See if a specialized converter is known to the desired matrix class. 4468 3) See if a good general converter is registered for the desired class 4469 (as of 6/27/03 only MATMPIADJ falls into this category). 4470 4) See if a good general converter is known for the current matrix. 4471 5) Use a really basic converter. 4472 */ 4473 4474 /* 0) See if newtype is a superclass of the current matrix. 4475 i.e mat is mpiaij and newtype is aij */ 4476 for (i = 0; i < 2; i++) { 4477 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4478 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4479 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4480 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4481 if (flg) { 4482 if (reuse == MAT_INPLACE_MATRIX) { 4483 PetscCall(PetscInfo(mat, "Early return\n")); 4484 PetscFunctionReturn(PETSC_SUCCESS); 4485 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4486 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4487 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4488 PetscFunctionReturn(PETSC_SUCCESS); 4489 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4490 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4491 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4492 PetscFunctionReturn(PETSC_SUCCESS); 4493 } 4494 } 4495 } 4496 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4497 for (i = 0; i < 3; i++) { 4498 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4499 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4500 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4501 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4502 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4503 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4504 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4505 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4506 if (conv) goto foundconv; 4507 } 4508 4509 /* 2) See if a specialized converter is known to the desired matrix class. */ 4510 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4511 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4512 PetscCall(MatSetType(B, newtype)); 4513 for (i = 0; i < 3; i++) { 4514 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4515 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4516 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4517 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4518 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4519 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4520 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4521 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4522 if (conv) { 4523 PetscCall(MatDestroy(&B)); 4524 goto foundconv; 4525 } 4526 } 4527 4528 /* 3) See if a good general converter is registered for the desired class */ 4529 conv = B->ops->convertfrom; 4530 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4531 PetscCall(MatDestroy(&B)); 4532 if (conv) goto foundconv; 4533 4534 /* 4) See if a good general converter is known for the current matrix */ 4535 if (mat->ops->convert) conv = mat->ops->convert; 4536 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4537 if (conv) goto foundconv; 4538 4539 /* 5) Use a really basic converter. */ 4540 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4541 conv = MatConvert_Basic; 4542 4543 foundconv: 4544 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4545 PetscCall((*conv)(mat, newtype, reuse, M)); 4546 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4547 /* the block sizes must be same if the mappings are copied over */ 4548 (*M)->rmap->bs = mat->rmap->bs; 4549 (*M)->cmap->bs = mat->cmap->bs; 4550 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4551 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4552 (*M)->rmap->mapping = mat->rmap->mapping; 4553 (*M)->cmap->mapping = mat->cmap->mapping; 4554 } 4555 (*M)->stencil.dim = mat->stencil.dim; 4556 (*M)->stencil.noc = mat->stencil.noc; 4557 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4558 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4559 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4560 } 4561 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4562 } 4563 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4564 4565 /* Copy Mat options */ 4566 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4567 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4568 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4569 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4570 PetscFunctionReturn(PETSC_SUCCESS); 4571 } 4572 4573 /*@ 4574 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4575 4576 Not Collective 4577 4578 Input Parameter: 4579 . mat - the matrix, must be a factored matrix 4580 4581 Output Parameter: 4582 . type - the string name of the package (do not free this string) 4583 4584 Level: intermediate 4585 4586 Fortran Note: 4587 Pass in an empty string that is long enough and the package name will be copied into it. 4588 4589 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4590 @*/ 4591 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4592 { 4593 PetscErrorCode (*conv)(Mat, MatSolverType *); 4594 4595 PetscFunctionBegin; 4596 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4597 PetscValidType(mat, 1); 4598 PetscAssertPointer(type, 2); 4599 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4600 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4601 if (conv) PetscCall((*conv)(mat, type)); 4602 else *type = MATSOLVERPETSC; 4603 PetscFunctionReturn(PETSC_SUCCESS); 4604 } 4605 4606 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4607 struct _MatSolverTypeForSpecifcType { 4608 MatType mtype; 4609 /* no entry for MAT_FACTOR_NONE */ 4610 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4611 MatSolverTypeForSpecifcType next; 4612 }; 4613 4614 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4615 struct _MatSolverTypeHolder { 4616 char *name; 4617 MatSolverTypeForSpecifcType handlers; 4618 MatSolverTypeHolder next; 4619 }; 4620 4621 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4622 4623 /*@C 4624 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4625 4626 Logically Collective, No Fortran Support 4627 4628 Input Parameters: 4629 + package - name of the package, for example petsc or superlu 4630 . mtype - the matrix type that works with this package 4631 . ftype - the type of factorization supported by the package 4632 - createfactor - routine that will create the factored matrix ready to be used 4633 4634 Level: developer 4635 4636 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4637 `MatGetFactor()` 4638 @*/ 4639 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4640 { 4641 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4642 PetscBool flg; 4643 MatSolverTypeForSpecifcType inext, iprev = NULL; 4644 4645 PetscFunctionBegin; 4646 PetscCall(MatInitializePackage()); 4647 if (!next) { 4648 PetscCall(PetscNew(&MatSolverTypeHolders)); 4649 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4650 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4651 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4652 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4653 PetscFunctionReturn(PETSC_SUCCESS); 4654 } 4655 while (next) { 4656 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4657 if (flg) { 4658 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4659 inext = next->handlers; 4660 while (inext) { 4661 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4662 if (flg) { 4663 inext->createfactor[(int)ftype - 1] = createfactor; 4664 PetscFunctionReturn(PETSC_SUCCESS); 4665 } 4666 iprev = inext; 4667 inext = inext->next; 4668 } 4669 PetscCall(PetscNew(&iprev->next)); 4670 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4671 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4672 PetscFunctionReturn(PETSC_SUCCESS); 4673 } 4674 prev = next; 4675 next = next->next; 4676 } 4677 PetscCall(PetscNew(&prev->next)); 4678 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4679 PetscCall(PetscNew(&prev->next->handlers)); 4680 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4681 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4682 PetscFunctionReturn(PETSC_SUCCESS); 4683 } 4684 4685 /*@C 4686 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4687 4688 Input Parameters: 4689 + 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 4690 . ftype - the type of factorization supported by the type 4691 - mtype - the matrix type that works with this type 4692 4693 Output Parameters: 4694 + foundtype - `PETSC_TRUE` if the type was registered 4695 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4696 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4697 4698 Calling sequence of `createfactor`: 4699 + A - the matrix providing the factor matrix 4700 . ftype - the `MatFactorType` of the factor requested 4701 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4702 4703 Level: developer 4704 4705 Note: 4706 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4707 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4708 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4709 4710 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4711 `MatInitializePackage()` 4712 @*/ 4713 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4714 { 4715 MatSolverTypeHolder next = MatSolverTypeHolders; 4716 PetscBool flg; 4717 MatSolverTypeForSpecifcType inext; 4718 4719 PetscFunctionBegin; 4720 if (foundtype) *foundtype = PETSC_FALSE; 4721 if (foundmtype) *foundmtype = PETSC_FALSE; 4722 if (createfactor) *createfactor = NULL; 4723 4724 if (type) { 4725 while (next) { 4726 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4727 if (flg) { 4728 if (foundtype) *foundtype = PETSC_TRUE; 4729 inext = next->handlers; 4730 while (inext) { 4731 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4732 if (flg) { 4733 if (foundmtype) *foundmtype = PETSC_TRUE; 4734 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4735 PetscFunctionReturn(PETSC_SUCCESS); 4736 } 4737 inext = inext->next; 4738 } 4739 } 4740 next = next->next; 4741 } 4742 } else { 4743 while (next) { 4744 inext = next->handlers; 4745 while (inext) { 4746 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4747 if (flg && inext->createfactor[(int)ftype - 1]) { 4748 if (foundtype) *foundtype = PETSC_TRUE; 4749 if (foundmtype) *foundmtype = PETSC_TRUE; 4750 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4751 PetscFunctionReturn(PETSC_SUCCESS); 4752 } 4753 inext = inext->next; 4754 } 4755 next = next->next; 4756 } 4757 /* try with base classes inext->mtype */ 4758 next = MatSolverTypeHolders; 4759 while (next) { 4760 inext = next->handlers; 4761 while (inext) { 4762 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4763 if (flg && inext->createfactor[(int)ftype - 1]) { 4764 if (foundtype) *foundtype = PETSC_TRUE; 4765 if (foundmtype) *foundmtype = PETSC_TRUE; 4766 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4767 PetscFunctionReturn(PETSC_SUCCESS); 4768 } 4769 inext = inext->next; 4770 } 4771 next = next->next; 4772 } 4773 } 4774 PetscFunctionReturn(PETSC_SUCCESS); 4775 } 4776 4777 PetscErrorCode MatSolverTypeDestroy(void) 4778 { 4779 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4780 MatSolverTypeForSpecifcType inext, iprev; 4781 4782 PetscFunctionBegin; 4783 while (next) { 4784 PetscCall(PetscFree(next->name)); 4785 inext = next->handlers; 4786 while (inext) { 4787 PetscCall(PetscFree(inext->mtype)); 4788 iprev = inext; 4789 inext = inext->next; 4790 PetscCall(PetscFree(iprev)); 4791 } 4792 prev = next; 4793 next = next->next; 4794 PetscCall(PetscFree(prev)); 4795 } 4796 MatSolverTypeHolders = NULL; 4797 PetscFunctionReturn(PETSC_SUCCESS); 4798 } 4799 4800 /*@ 4801 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4802 4803 Logically Collective 4804 4805 Input Parameter: 4806 . mat - the matrix 4807 4808 Output Parameter: 4809 . flg - `PETSC_TRUE` if uses the ordering 4810 4811 Level: developer 4812 4813 Note: 4814 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4815 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4816 4817 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4818 @*/ 4819 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4820 { 4821 PetscFunctionBegin; 4822 *flg = mat->canuseordering; 4823 PetscFunctionReturn(PETSC_SUCCESS); 4824 } 4825 4826 /*@ 4827 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4828 4829 Logically Collective 4830 4831 Input Parameters: 4832 + mat - the matrix obtained with `MatGetFactor()` 4833 - ftype - the factorization type to be used 4834 4835 Output Parameter: 4836 . otype - the preferred ordering type 4837 4838 Level: developer 4839 4840 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4841 @*/ 4842 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4843 { 4844 PetscFunctionBegin; 4845 *otype = mat->preferredordering[ftype]; 4846 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4847 PetscFunctionReturn(PETSC_SUCCESS); 4848 } 4849 4850 /*@ 4851 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4852 4853 Collective 4854 4855 Input Parameters: 4856 + mat - the matrix 4857 . 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 4858 the other criteria is returned 4859 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4860 4861 Output Parameter: 4862 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4863 4864 Options Database Keys: 4865 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4866 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory. 4867 One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices. 4868 4869 Level: intermediate 4870 4871 Notes: 4872 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4873 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4874 4875 Users usually access the factorization solvers via `KSP` 4876 4877 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4878 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 4879 4880 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4881 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4882 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4883 4884 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4885 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4886 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4887 4888 Developer Note: 4889 This should actually be called `MatCreateFactor()` since it creates a new factor object 4890 4891 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4892 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4893 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4894 @*/ 4895 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4896 { 4897 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4898 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4899 4900 PetscFunctionBegin; 4901 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4902 PetscValidType(mat, 1); 4903 4904 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4905 MatCheckPreallocated(mat, 1); 4906 4907 PetscCall(MatIsShell(mat, &shell)); 4908 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4909 if (hasop) { 4910 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4911 PetscFunctionReturn(PETSC_SUCCESS); 4912 } 4913 4914 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4915 if (!foundtype) { 4916 if (type) { 4917 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], 4918 ((PetscObject)mat)->type_name, type); 4919 } else { 4920 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); 4921 } 4922 } 4923 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4924 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); 4925 4926 PetscCall((*conv)(mat, ftype, f)); 4927 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4928 PetscFunctionReturn(PETSC_SUCCESS); 4929 } 4930 4931 /*@ 4932 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4933 4934 Not Collective 4935 4936 Input Parameters: 4937 + mat - the matrix 4938 . type - name of solver type, for example, superlu, petsc (to use PETSc's default) 4939 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4940 4941 Output Parameter: 4942 . flg - PETSC_TRUE if the factorization is available 4943 4944 Level: intermediate 4945 4946 Notes: 4947 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4948 such as pastix, superlu, mumps etc. 4949 4950 PETSc must have been ./configure to use the external solver, using the option --download-package 4951 4952 Developer Note: 4953 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4954 4955 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4956 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4957 @*/ 4958 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4959 { 4960 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4961 4962 PetscFunctionBegin; 4963 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4964 PetscAssertPointer(flg, 4); 4965 4966 *flg = PETSC_FALSE; 4967 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4968 4969 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4970 MatCheckPreallocated(mat, 1); 4971 4972 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4973 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4974 PetscFunctionReturn(PETSC_SUCCESS); 4975 } 4976 4977 /*@ 4978 MatDuplicate - Duplicates a matrix including the non-zero structure. 4979 4980 Collective 4981 4982 Input Parameters: 4983 + mat - the matrix 4984 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4985 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4986 4987 Output Parameter: 4988 . M - pointer to place new matrix 4989 4990 Level: intermediate 4991 4992 Notes: 4993 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4994 4995 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4996 4997 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. 4998 4999 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 5000 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 5001 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 5002 5003 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 5004 @*/ 5005 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 5006 { 5007 Mat B; 5008 VecType vtype; 5009 PetscInt i; 5010 PetscObject dm, container_h, container_d; 5011 void (*viewf)(void); 5012 5013 PetscFunctionBegin; 5014 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5015 PetscValidType(mat, 1); 5016 PetscAssertPointer(M, 3); 5017 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 5018 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5019 MatCheckPreallocated(mat, 1); 5020 5021 *M = NULL; 5022 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 5023 PetscUseTypeMethod(mat, duplicate, op, M); 5024 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 5025 B = *M; 5026 5027 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 5028 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 5029 PetscCall(MatGetVecType(mat, &vtype)); 5030 PetscCall(MatSetVecType(B, vtype)); 5031 5032 B->stencil.dim = mat->stencil.dim; 5033 B->stencil.noc = mat->stencil.noc; 5034 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 5035 B->stencil.dims[i] = mat->stencil.dims[i]; 5036 B->stencil.starts[i] = mat->stencil.starts[i]; 5037 } 5038 5039 B->nooffproczerorows = mat->nooffproczerorows; 5040 B->nooffprocentries = mat->nooffprocentries; 5041 5042 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 5043 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 5044 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 5045 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5046 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5047 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5048 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5049 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5050 PetscFunctionReturn(PETSC_SUCCESS); 5051 } 5052 5053 /*@ 5054 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5055 5056 Logically Collective 5057 5058 Input Parameter: 5059 . mat - the matrix 5060 5061 Output Parameter: 5062 . v - the diagonal of the matrix 5063 5064 Level: intermediate 5065 5066 Note: 5067 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5068 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5069 is larger than `ndiag`, the values of the remaining entries are unspecified. 5070 5071 Currently only correct in parallel for square matrices. 5072 5073 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5074 @*/ 5075 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5076 { 5077 PetscFunctionBegin; 5078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5079 PetscValidType(mat, 1); 5080 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5081 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5082 MatCheckPreallocated(mat, 1); 5083 if (PetscDefined(USE_DEBUG)) { 5084 PetscInt nv, row, col, ndiag; 5085 5086 PetscCall(VecGetLocalSize(v, &nv)); 5087 PetscCall(MatGetLocalSize(mat, &row, &col)); 5088 ndiag = PetscMin(row, col); 5089 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); 5090 } 5091 5092 PetscUseTypeMethod(mat, getdiagonal, v); 5093 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5094 PetscFunctionReturn(PETSC_SUCCESS); 5095 } 5096 5097 /*@ 5098 MatGetRowMin - Gets the minimum value (of the real part) of each 5099 row of the matrix 5100 5101 Logically Collective 5102 5103 Input Parameter: 5104 . mat - the matrix 5105 5106 Output Parameters: 5107 + v - the vector for storing the maximums 5108 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5109 5110 Level: intermediate 5111 5112 Note: 5113 The result of this call are the same as if one converted the matrix to dense format 5114 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5115 5116 This code is only implemented for a couple of matrix formats. 5117 5118 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5119 `MatGetRowMax()` 5120 @*/ 5121 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5122 { 5123 PetscFunctionBegin; 5124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5125 PetscValidType(mat, 1); 5126 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5127 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5128 5129 if (!mat->cmap->N) { 5130 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5131 if (idx) { 5132 PetscInt i, m = mat->rmap->n; 5133 for (i = 0; i < m; i++) idx[i] = -1; 5134 } 5135 } else { 5136 MatCheckPreallocated(mat, 1); 5137 } 5138 PetscUseTypeMethod(mat, getrowmin, v, idx); 5139 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5140 PetscFunctionReturn(PETSC_SUCCESS); 5141 } 5142 5143 /*@ 5144 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5145 row of the matrix 5146 5147 Logically Collective 5148 5149 Input Parameter: 5150 . mat - the matrix 5151 5152 Output Parameters: 5153 + v - the vector for storing the minimums 5154 - idx - the indices of the column found for each row (or `NULL` if not needed) 5155 5156 Level: intermediate 5157 5158 Notes: 5159 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5160 row is 0 (the first column). 5161 5162 This code is only implemented for a couple of matrix formats. 5163 5164 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5165 @*/ 5166 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5167 { 5168 PetscFunctionBegin; 5169 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5170 PetscValidType(mat, 1); 5171 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5172 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5173 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5174 5175 if (!mat->cmap->N) { 5176 PetscCall(VecSet(v, 0.0)); 5177 if (idx) { 5178 PetscInt i, m = mat->rmap->n; 5179 for (i = 0; i < m; i++) idx[i] = -1; 5180 } 5181 } else { 5182 MatCheckPreallocated(mat, 1); 5183 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5184 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5185 } 5186 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5187 PetscFunctionReturn(PETSC_SUCCESS); 5188 } 5189 5190 /*@ 5191 MatGetRowMax - Gets the maximum value (of the real part) of each 5192 row of the matrix 5193 5194 Logically Collective 5195 5196 Input Parameter: 5197 . mat - the matrix 5198 5199 Output Parameters: 5200 + v - the vector for storing the maximums 5201 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5202 5203 Level: intermediate 5204 5205 Notes: 5206 The result of this call are the same as if one converted the matrix to dense format 5207 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5208 5209 This code is only implemented for a couple of matrix formats. 5210 5211 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5212 @*/ 5213 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5214 { 5215 PetscFunctionBegin; 5216 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5217 PetscValidType(mat, 1); 5218 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5219 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5220 5221 if (!mat->cmap->N) { 5222 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5223 if (idx) { 5224 PetscInt i, m = mat->rmap->n; 5225 for (i = 0; i < m; i++) idx[i] = -1; 5226 } 5227 } else { 5228 MatCheckPreallocated(mat, 1); 5229 PetscUseTypeMethod(mat, getrowmax, v, idx); 5230 } 5231 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5232 PetscFunctionReturn(PETSC_SUCCESS); 5233 } 5234 5235 /*@ 5236 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5237 row of the matrix 5238 5239 Logically Collective 5240 5241 Input Parameter: 5242 . mat - the matrix 5243 5244 Output Parameters: 5245 + v - the vector for storing the maximums 5246 - idx - the indices of the column found for each row (or `NULL` if not needed) 5247 5248 Level: intermediate 5249 5250 Notes: 5251 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5252 row is 0 (the first column). 5253 5254 This code is only implemented for a couple of matrix formats. 5255 5256 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5257 @*/ 5258 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5259 { 5260 PetscFunctionBegin; 5261 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5262 PetscValidType(mat, 1); 5263 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5264 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5265 5266 if (!mat->cmap->N) { 5267 PetscCall(VecSet(v, 0.0)); 5268 if (idx) { 5269 PetscInt i, m = mat->rmap->n; 5270 for (i = 0; i < m; i++) idx[i] = -1; 5271 } 5272 } else { 5273 MatCheckPreallocated(mat, 1); 5274 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5275 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5276 } 5277 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5278 PetscFunctionReturn(PETSC_SUCCESS); 5279 } 5280 5281 /*@ 5282 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5283 5284 Logically Collective 5285 5286 Input Parameter: 5287 . mat - the matrix 5288 5289 Output Parameter: 5290 . v - the vector for storing the sum 5291 5292 Level: intermediate 5293 5294 This code is only implemented for a couple of matrix formats. 5295 5296 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5297 @*/ 5298 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5299 { 5300 PetscFunctionBegin; 5301 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5302 PetscValidType(mat, 1); 5303 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5304 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5305 5306 if (!mat->cmap->N) { 5307 PetscCall(VecSet(v, 0.0)); 5308 } else { 5309 MatCheckPreallocated(mat, 1); 5310 PetscUseTypeMethod(mat, getrowsumabs, v); 5311 } 5312 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5313 PetscFunctionReturn(PETSC_SUCCESS); 5314 } 5315 5316 /*@ 5317 MatGetRowSum - Gets the sum of each row of the matrix 5318 5319 Logically or Neighborhood Collective 5320 5321 Input Parameter: 5322 . mat - the matrix 5323 5324 Output Parameter: 5325 . v - the vector for storing the sum of rows 5326 5327 Level: intermediate 5328 5329 Note: 5330 This code is slow since it is not currently specialized for different formats 5331 5332 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5333 @*/ 5334 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5335 { 5336 Vec ones; 5337 5338 PetscFunctionBegin; 5339 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5340 PetscValidType(mat, 1); 5341 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5342 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5343 MatCheckPreallocated(mat, 1); 5344 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5345 PetscCall(VecSet(ones, 1.)); 5346 PetscCall(MatMult(mat, ones, v)); 5347 PetscCall(VecDestroy(&ones)); 5348 PetscFunctionReturn(PETSC_SUCCESS); 5349 } 5350 5351 /*@ 5352 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5353 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5354 5355 Collective 5356 5357 Input Parameter: 5358 . mat - the matrix to provide the transpose 5359 5360 Output Parameter: 5361 . 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 5362 5363 Level: advanced 5364 5365 Note: 5366 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 5367 routine allows bypassing that call. 5368 5369 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5370 @*/ 5371 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5372 { 5373 MatParentState *rb = NULL; 5374 5375 PetscFunctionBegin; 5376 PetscCall(PetscNew(&rb)); 5377 rb->id = ((PetscObject)mat)->id; 5378 rb->state = 0; 5379 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5380 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5381 PetscFunctionReturn(PETSC_SUCCESS); 5382 } 5383 5384 /*@ 5385 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5386 5387 Collective 5388 5389 Input Parameters: 5390 + mat - the matrix to transpose 5391 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5392 5393 Output Parameter: 5394 . B - the transpose of the matrix 5395 5396 Level: intermediate 5397 5398 Notes: 5399 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5400 5401 `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX` to store the transpose. If you already have a matrix to contain the 5402 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5403 5404 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. 5405 5406 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5407 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5408 5409 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5410 5411 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5412 5413 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5414 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5415 @*/ 5416 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5417 { 5418 PetscContainer rB = NULL; 5419 MatParentState *rb = NULL; 5420 5421 PetscFunctionBegin; 5422 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5423 PetscValidType(mat, 1); 5424 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5425 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5426 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5427 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5428 MatCheckPreallocated(mat, 1); 5429 if (reuse == MAT_REUSE_MATRIX) { 5430 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5431 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5432 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5433 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5434 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5435 } 5436 5437 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5438 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5439 PetscUseTypeMethod(mat, transpose, reuse, B); 5440 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5441 } 5442 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5443 5444 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5445 if (reuse != MAT_INPLACE_MATRIX) { 5446 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5447 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5448 rb->state = ((PetscObject)mat)->state; 5449 rb->nonzerostate = mat->nonzerostate; 5450 } 5451 PetscFunctionReturn(PETSC_SUCCESS); 5452 } 5453 5454 /*@ 5455 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5456 5457 Collective 5458 5459 Input Parameter: 5460 . A - the matrix to transpose 5461 5462 Output Parameter: 5463 . 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 5464 numerical portion. 5465 5466 Level: intermediate 5467 5468 Note: 5469 This is not supported for many matrix types, use `MatTranspose()` in those cases 5470 5471 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5472 @*/ 5473 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5474 { 5475 PetscFunctionBegin; 5476 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5477 PetscValidType(A, 1); 5478 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5479 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5480 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5481 PetscUseTypeMethod(A, transposesymbolic, B); 5482 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5483 5484 PetscCall(MatTransposeSetPrecursor(A, *B)); 5485 PetscFunctionReturn(PETSC_SUCCESS); 5486 } 5487 5488 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5489 { 5490 PetscContainer rB; 5491 MatParentState *rb; 5492 5493 PetscFunctionBegin; 5494 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5495 PetscValidType(A, 1); 5496 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5497 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5498 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5499 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5500 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5501 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5502 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5503 PetscFunctionReturn(PETSC_SUCCESS); 5504 } 5505 5506 /*@ 5507 MatIsTranspose - Test whether a matrix is another one's transpose, 5508 or its own, in which case it tests symmetry. 5509 5510 Collective 5511 5512 Input Parameters: 5513 + A - the matrix to test 5514 . B - the matrix to test against, this can equal the first parameter 5515 - tol - tolerance, differences between entries smaller than this are counted as zero 5516 5517 Output Parameter: 5518 . flg - the result 5519 5520 Level: intermediate 5521 5522 Notes: 5523 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5524 test involves parallel copies of the block off-diagonal parts of the matrix. 5525 5526 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5527 @*/ 5528 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5529 { 5530 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5531 5532 PetscFunctionBegin; 5533 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5534 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5535 PetscAssertPointer(flg, 4); 5536 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5537 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5538 *flg = PETSC_FALSE; 5539 if (f && g) { 5540 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5541 PetscCall((*f)(A, B, tol, flg)); 5542 } else { 5543 MatType mattype; 5544 5545 PetscCall(MatGetType(f ? B : A, &mattype)); 5546 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5547 } 5548 PetscFunctionReturn(PETSC_SUCCESS); 5549 } 5550 5551 /*@ 5552 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5553 5554 Collective 5555 5556 Input Parameters: 5557 + mat - the matrix to transpose and complex conjugate 5558 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5559 5560 Output Parameter: 5561 . B - the Hermitian transpose 5562 5563 Level: intermediate 5564 5565 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5566 @*/ 5567 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5568 { 5569 PetscFunctionBegin; 5570 PetscCall(MatTranspose(mat, reuse, B)); 5571 #if defined(PETSC_USE_COMPLEX) 5572 PetscCall(MatConjugate(*B)); 5573 #endif 5574 PetscFunctionReturn(PETSC_SUCCESS); 5575 } 5576 5577 /*@ 5578 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5579 5580 Collective 5581 5582 Input Parameters: 5583 + A - the matrix to test 5584 . B - the matrix to test against, this can equal the first parameter 5585 - tol - tolerance, differences between entries smaller than this are counted as zero 5586 5587 Output Parameter: 5588 . flg - the result 5589 5590 Level: intermediate 5591 5592 Notes: 5593 Only available for `MATAIJ` matrices. 5594 5595 The sequential algorithm 5596 has a running time of the order of the number of nonzeros; the parallel 5597 test involves parallel copies of the block off-diagonal parts of the matrix. 5598 5599 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5600 @*/ 5601 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5602 { 5603 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5604 5605 PetscFunctionBegin; 5606 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5607 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5608 PetscAssertPointer(flg, 4); 5609 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5610 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5611 if (f && g) { 5612 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5613 PetscCall((*f)(A, B, tol, flg)); 5614 } 5615 PetscFunctionReturn(PETSC_SUCCESS); 5616 } 5617 5618 /*@ 5619 MatPermute - Creates a new matrix with rows and columns permuted from the 5620 original. 5621 5622 Collective 5623 5624 Input Parameters: 5625 + mat - the matrix to permute 5626 . row - row permutation, each processor supplies only the permutation for its rows 5627 - col - column permutation, each processor supplies only the permutation for its columns 5628 5629 Output Parameter: 5630 . B - the permuted matrix 5631 5632 Level: advanced 5633 5634 Note: 5635 The index sets map from row/col of permuted matrix to row/col of original matrix. 5636 The index sets should be on the same communicator as mat and have the same local sizes. 5637 5638 Developer Note: 5639 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5640 exploit the fact that row and col are permutations, consider implementing the 5641 more general `MatCreateSubMatrix()` instead. 5642 5643 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5644 @*/ 5645 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5646 { 5647 PetscFunctionBegin; 5648 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5649 PetscValidType(mat, 1); 5650 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5651 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5652 PetscAssertPointer(B, 4); 5653 PetscCheckSameComm(mat, 1, row, 2); 5654 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5655 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5656 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5657 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5658 MatCheckPreallocated(mat, 1); 5659 5660 if (mat->ops->permute) { 5661 PetscUseTypeMethod(mat, permute, row, col, B); 5662 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5663 } else { 5664 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5665 } 5666 PetscFunctionReturn(PETSC_SUCCESS); 5667 } 5668 5669 /*@ 5670 MatEqual - Compares two matrices. 5671 5672 Collective 5673 5674 Input Parameters: 5675 + A - the first matrix 5676 - B - the second matrix 5677 5678 Output Parameter: 5679 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5680 5681 Level: intermediate 5682 5683 .seealso: [](ch_matrices), `Mat` 5684 @*/ 5685 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5686 { 5687 PetscFunctionBegin; 5688 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5689 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5690 PetscValidType(A, 1); 5691 PetscValidType(B, 2); 5692 PetscAssertPointer(flg, 3); 5693 PetscCheckSameComm(A, 1, B, 2); 5694 MatCheckPreallocated(A, 1); 5695 MatCheckPreallocated(B, 2); 5696 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5697 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5698 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, 5699 B->cmap->N); 5700 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5701 PetscUseTypeMethod(A, equal, B, flg); 5702 } else { 5703 PetscCall(MatMultEqual(A, B, 10, flg)); 5704 } 5705 PetscFunctionReturn(PETSC_SUCCESS); 5706 } 5707 5708 /*@ 5709 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5710 matrices that are stored as vectors. Either of the two scaling 5711 matrices can be `NULL`. 5712 5713 Collective 5714 5715 Input Parameters: 5716 + mat - the matrix to be scaled 5717 . l - the left scaling vector (or `NULL`) 5718 - r - the right scaling vector (or `NULL`) 5719 5720 Level: intermediate 5721 5722 Note: 5723 `MatDiagonalScale()` computes $A = LAR$, where 5724 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5725 The L scales the rows of the matrix, the R scales the columns of the matrix. 5726 5727 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5728 @*/ 5729 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5730 { 5731 PetscFunctionBegin; 5732 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5733 PetscValidType(mat, 1); 5734 if (l) { 5735 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5736 PetscCheckSameComm(mat, 1, l, 2); 5737 } 5738 if (r) { 5739 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5740 PetscCheckSameComm(mat, 1, r, 3); 5741 } 5742 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5743 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5744 MatCheckPreallocated(mat, 1); 5745 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5746 5747 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5748 PetscUseTypeMethod(mat, diagonalscale, l, r); 5749 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5750 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5751 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5752 PetscFunctionReturn(PETSC_SUCCESS); 5753 } 5754 5755 /*@ 5756 MatScale - Scales all elements of a matrix by a given number. 5757 5758 Logically Collective 5759 5760 Input Parameters: 5761 + mat - the matrix to be scaled 5762 - a - the scaling value 5763 5764 Level: intermediate 5765 5766 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5767 @*/ 5768 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5769 { 5770 PetscFunctionBegin; 5771 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5772 PetscValidType(mat, 1); 5773 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5774 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5775 PetscValidLogicalCollectiveScalar(mat, a, 2); 5776 MatCheckPreallocated(mat, 1); 5777 5778 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5779 if (a != (PetscScalar)1.0) { 5780 PetscUseTypeMethod(mat, scale, a); 5781 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5782 } 5783 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5784 PetscFunctionReturn(PETSC_SUCCESS); 5785 } 5786 5787 /*@ 5788 MatNorm - Calculates various norms of a matrix. 5789 5790 Collective 5791 5792 Input Parameters: 5793 + mat - the matrix 5794 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5795 5796 Output Parameter: 5797 . nrm - the resulting norm 5798 5799 Level: intermediate 5800 5801 .seealso: [](ch_matrices), `Mat` 5802 @*/ 5803 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5804 { 5805 PetscFunctionBegin; 5806 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5807 PetscValidType(mat, 1); 5808 PetscAssertPointer(nrm, 3); 5809 5810 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5811 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5812 MatCheckPreallocated(mat, 1); 5813 5814 PetscUseTypeMethod(mat, norm, type, nrm); 5815 PetscFunctionReturn(PETSC_SUCCESS); 5816 } 5817 5818 /* 5819 This variable is used to prevent counting of MatAssemblyBegin() that 5820 are called from within a MatAssemblyEnd(). 5821 */ 5822 static PetscInt MatAssemblyEnd_InUse = 0; 5823 /*@ 5824 MatAssemblyBegin - Begins assembling the matrix. This routine should 5825 be called after completing all calls to `MatSetValues()`. 5826 5827 Collective 5828 5829 Input Parameters: 5830 + mat - the matrix 5831 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5832 5833 Level: beginner 5834 5835 Notes: 5836 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5837 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5838 5839 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5840 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5841 using the matrix. 5842 5843 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5844 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 5845 a global collective operation requiring all processes that share the matrix. 5846 5847 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5848 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5849 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5850 5851 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5852 @*/ 5853 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5854 { 5855 PetscFunctionBegin; 5856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5857 PetscValidType(mat, 1); 5858 MatCheckPreallocated(mat, 1); 5859 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5860 if (mat->assembled) { 5861 mat->was_assembled = PETSC_TRUE; 5862 mat->assembled = PETSC_FALSE; 5863 } 5864 5865 if (!MatAssemblyEnd_InUse) { 5866 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5867 PetscTryTypeMethod(mat, assemblybegin, type); 5868 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5869 } else PetscTryTypeMethod(mat, assemblybegin, type); 5870 PetscFunctionReturn(PETSC_SUCCESS); 5871 } 5872 5873 /*@ 5874 MatAssembled - Indicates if a matrix has been assembled and is ready for 5875 use; for example, in matrix-vector product. 5876 5877 Not Collective 5878 5879 Input Parameter: 5880 . mat - the matrix 5881 5882 Output Parameter: 5883 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5884 5885 Level: advanced 5886 5887 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5888 @*/ 5889 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5890 { 5891 PetscFunctionBegin; 5892 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5893 PetscAssertPointer(assembled, 2); 5894 *assembled = mat->assembled; 5895 PetscFunctionReturn(PETSC_SUCCESS); 5896 } 5897 5898 /*@ 5899 MatAssemblyEnd - Completes assembling the matrix. This routine should 5900 be called after `MatAssemblyBegin()`. 5901 5902 Collective 5903 5904 Input Parameters: 5905 + mat - the matrix 5906 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5907 5908 Options Database Keys: 5909 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5910 . -mat_view ::ascii_info_detail - Prints more detailed info 5911 . -mat_view - Prints matrix in ASCII format 5912 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5913 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5914 . -display <name> - Sets display name (default is host) 5915 . -draw_pause <sec> - Sets number of seconds to pause after display 5916 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5917 . -viewer_socket_machine <machine> - Machine to use for socket 5918 . -viewer_socket_port <port> - Port number to use for socket 5919 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5920 5921 Level: beginner 5922 5923 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5924 @*/ 5925 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5926 { 5927 static PetscInt inassm = 0; 5928 PetscBool flg = PETSC_FALSE; 5929 5930 PetscFunctionBegin; 5931 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5932 PetscValidType(mat, 1); 5933 5934 inassm++; 5935 MatAssemblyEnd_InUse++; 5936 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5937 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5938 PetscTryTypeMethod(mat, assemblyend, type); 5939 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5940 } else PetscTryTypeMethod(mat, assemblyend, type); 5941 5942 /* Flush assembly is not a true assembly */ 5943 if (type != MAT_FLUSH_ASSEMBLY) { 5944 if (mat->num_ass) { 5945 if (!mat->symmetry_eternal) { 5946 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5947 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5948 } 5949 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5950 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5951 } 5952 mat->num_ass++; 5953 mat->assembled = PETSC_TRUE; 5954 mat->ass_nonzerostate = mat->nonzerostate; 5955 } 5956 5957 mat->insertmode = NOT_SET_VALUES; 5958 MatAssemblyEnd_InUse--; 5959 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5960 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5961 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5962 5963 if (mat->checksymmetryonassembly) { 5964 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5965 if (flg) { 5966 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5967 } else { 5968 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5969 } 5970 } 5971 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5972 } 5973 inassm--; 5974 PetscFunctionReturn(PETSC_SUCCESS); 5975 } 5976 5977 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5978 /*@ 5979 MatSetOption - Sets a parameter option for a matrix. Some options 5980 may be specific to certain storage formats. Some options 5981 determine how values will be inserted (or added). Sorted, 5982 row-oriented input will generally assemble the fastest. The default 5983 is row-oriented. 5984 5985 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5986 5987 Input Parameters: 5988 + mat - the matrix 5989 . op - the option, one of those listed below (and possibly others), 5990 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5991 5992 Options Describing Matrix Structure: 5993 + `MAT_SPD` - symmetric positive definite 5994 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5995 . `MAT_HERMITIAN` - transpose is the complex conjugation 5996 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5997 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5998 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5999 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 6000 6001 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 6002 do not need to be computed (usually at a high cost) 6003 6004 Options For Use with `MatSetValues()`: 6005 Insert a logically dense subblock, which can be 6006 . `MAT_ROW_ORIENTED` - row-oriented (default) 6007 6008 These options reflect the data you pass in with `MatSetValues()`; it has 6009 nothing to do with how the data is stored internally in the matrix 6010 data structure. 6011 6012 When (re)assembling a matrix, we can restrict the input for 6013 efficiency/debugging purposes. These options include 6014 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 6015 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 6016 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 6017 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 6018 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 6019 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 6020 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 6021 performance for very large process counts. 6022 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 6023 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 6024 functions, instead sending only neighbor messages. 6025 6026 Level: intermediate 6027 6028 Notes: 6029 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 6030 6031 Some options are relevant only for particular matrix types and 6032 are thus ignored by others. Other options are not supported by 6033 certain matrix types and will generate an error message if set. 6034 6035 If using Fortran to compute a matrix, one may need to 6036 use the column-oriented option (or convert to the row-oriented 6037 format). 6038 6039 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6040 that would generate a new entry in the nonzero structure is instead 6041 ignored. Thus, if memory has not already been allocated for this particular 6042 data, then the insertion is ignored. For dense matrices, in which 6043 the entire array is allocated, no entries are ever ignored. 6044 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6045 6046 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6047 that would generate a new entry in the nonzero structure instead produces 6048 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 6049 6050 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6051 that would generate a new entry that has not been preallocated will 6052 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6053 only.) This is a useful flag when debugging matrix memory preallocation. 6054 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6055 6056 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6057 other processors should be dropped, rather than stashed. 6058 This is useful if you know that the "owning" processor is also 6059 always generating the correct matrix entries, so that PETSc need 6060 not transfer duplicate entries generated on another processor. 6061 6062 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6063 searches during matrix assembly. When this flag is set, the hash table 6064 is created during the first matrix assembly. This hash table is 6065 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6066 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6067 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6068 supported by `MATMPIBAIJ` format only. 6069 6070 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6071 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6072 6073 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6074 a zero location in the matrix 6075 6076 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6077 6078 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6079 zero row routines and thus improves performance for very large process counts. 6080 6081 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6082 part of the matrix (since they should match the upper triangular part). 6083 6084 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6085 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6086 with finite difference schemes with non-periodic boundary conditions. 6087 6088 Developer Note: 6089 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6090 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6091 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6092 not changed. 6093 6094 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6095 @*/ 6096 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6097 { 6098 PetscFunctionBegin; 6099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6100 if (op > 0) { 6101 PetscValidLogicalCollectiveEnum(mat, op, 2); 6102 PetscValidLogicalCollectiveBool(mat, flg, 3); 6103 } 6104 6105 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); 6106 6107 switch (op) { 6108 case MAT_FORCE_DIAGONAL_ENTRIES: 6109 mat->force_diagonals = flg; 6110 PetscFunctionReturn(PETSC_SUCCESS); 6111 case MAT_NO_OFF_PROC_ENTRIES: 6112 mat->nooffprocentries = flg; 6113 PetscFunctionReturn(PETSC_SUCCESS); 6114 case MAT_SUBSET_OFF_PROC_ENTRIES: 6115 mat->assembly_subset = flg; 6116 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6117 #if !defined(PETSC_HAVE_MPIUNI) 6118 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6119 #endif 6120 mat->stash.first_assembly_done = PETSC_FALSE; 6121 } 6122 PetscFunctionReturn(PETSC_SUCCESS); 6123 case MAT_NO_OFF_PROC_ZERO_ROWS: 6124 mat->nooffproczerorows = flg; 6125 PetscFunctionReturn(PETSC_SUCCESS); 6126 case MAT_SPD: 6127 if (flg) { 6128 mat->spd = PETSC_BOOL3_TRUE; 6129 mat->symmetric = PETSC_BOOL3_TRUE; 6130 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6131 } else { 6132 mat->spd = PETSC_BOOL3_FALSE; 6133 } 6134 break; 6135 case MAT_SYMMETRIC: 6136 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6137 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6138 #if !defined(PETSC_USE_COMPLEX) 6139 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6140 #endif 6141 break; 6142 case MAT_HERMITIAN: 6143 mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6144 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6145 #if !defined(PETSC_USE_COMPLEX) 6146 mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6147 #endif 6148 break; 6149 case MAT_STRUCTURALLY_SYMMETRIC: 6150 mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; 6151 break; 6152 case MAT_SYMMETRY_ETERNAL: 6153 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"); 6154 mat->symmetry_eternal = flg; 6155 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6156 break; 6157 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6158 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"); 6159 mat->structural_symmetry_eternal = flg; 6160 break; 6161 case MAT_SPD_ETERNAL: 6162 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"); 6163 mat->spd_eternal = flg; 6164 if (flg) { 6165 mat->structural_symmetry_eternal = PETSC_TRUE; 6166 mat->symmetry_eternal = PETSC_TRUE; 6167 } 6168 break; 6169 case MAT_STRUCTURE_ONLY: 6170 mat->structure_only = flg; 6171 break; 6172 case MAT_SORTED_FULL: 6173 mat->sortedfull = flg; 6174 break; 6175 default: 6176 break; 6177 } 6178 PetscTryTypeMethod(mat, setoption, op, flg); 6179 PetscFunctionReturn(PETSC_SUCCESS); 6180 } 6181 6182 /*@ 6183 MatGetOption - Gets a parameter option that has been set for a matrix. 6184 6185 Logically Collective 6186 6187 Input Parameters: 6188 + mat - the matrix 6189 - op - the option, this only responds to certain options, check the code for which ones 6190 6191 Output Parameter: 6192 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6193 6194 Level: intermediate 6195 6196 Notes: 6197 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6198 6199 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6200 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6201 6202 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6203 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6204 @*/ 6205 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6206 { 6207 PetscFunctionBegin; 6208 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6209 PetscValidType(mat, 1); 6210 6211 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); 6212 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()"); 6213 6214 switch (op) { 6215 case MAT_NO_OFF_PROC_ENTRIES: 6216 *flg = mat->nooffprocentries; 6217 break; 6218 case MAT_NO_OFF_PROC_ZERO_ROWS: 6219 *flg = mat->nooffproczerorows; 6220 break; 6221 case MAT_SYMMETRIC: 6222 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6223 break; 6224 case MAT_HERMITIAN: 6225 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6226 break; 6227 case MAT_STRUCTURALLY_SYMMETRIC: 6228 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6229 break; 6230 case MAT_SPD: 6231 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6232 break; 6233 case MAT_SYMMETRY_ETERNAL: 6234 *flg = mat->symmetry_eternal; 6235 break; 6236 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6237 *flg = mat->symmetry_eternal; 6238 break; 6239 default: 6240 break; 6241 } 6242 PetscFunctionReturn(PETSC_SUCCESS); 6243 } 6244 6245 /*@ 6246 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6247 this routine retains the old nonzero structure. 6248 6249 Logically Collective 6250 6251 Input Parameter: 6252 . mat - the matrix 6253 6254 Level: intermediate 6255 6256 Note: 6257 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. 6258 See the Performance chapter of the users manual for information on preallocating matrices. 6259 6260 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6261 @*/ 6262 PetscErrorCode MatZeroEntries(Mat mat) 6263 { 6264 PetscFunctionBegin; 6265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6266 PetscValidType(mat, 1); 6267 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6268 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"); 6269 MatCheckPreallocated(mat, 1); 6270 6271 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6272 PetscUseTypeMethod(mat, zeroentries); 6273 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6274 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6275 PetscFunctionReturn(PETSC_SUCCESS); 6276 } 6277 6278 /*@ 6279 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6280 of a set of rows and columns of a matrix. 6281 6282 Collective 6283 6284 Input Parameters: 6285 + mat - the matrix 6286 . numRows - the number of rows/columns to zero 6287 . rows - the global row indices 6288 . diag - value put in the diagonal of the eliminated rows 6289 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6290 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6291 6292 Level: intermediate 6293 6294 Notes: 6295 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6296 6297 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6298 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 6299 6300 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6301 Krylov method to take advantage of the known solution on the zeroed rows. 6302 6303 For the parallel case, all processes that share the matrix (i.e., 6304 those in the communicator used for matrix creation) MUST call this 6305 routine, regardless of whether any rows being zeroed are owned by 6306 them. 6307 6308 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6309 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 6310 missing. 6311 6312 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6313 list only rows local to itself). 6314 6315 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6316 6317 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6318 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6319 @*/ 6320 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6321 { 6322 PetscFunctionBegin; 6323 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6324 PetscValidType(mat, 1); 6325 if (numRows) PetscAssertPointer(rows, 3); 6326 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6327 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6328 MatCheckPreallocated(mat, 1); 6329 6330 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6331 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6332 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6333 PetscFunctionReturn(PETSC_SUCCESS); 6334 } 6335 6336 /*@ 6337 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6338 of a set of rows and columns of a matrix. 6339 6340 Collective 6341 6342 Input Parameters: 6343 + mat - the matrix 6344 . is - the rows to zero 6345 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6346 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6347 - b - optional vector of right-hand side, that will be adjusted by provided solution 6348 6349 Level: intermediate 6350 6351 Note: 6352 See `MatZeroRowsColumns()` for details on how this routine operates. 6353 6354 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6355 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6356 @*/ 6357 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6358 { 6359 PetscInt numRows; 6360 const PetscInt *rows; 6361 6362 PetscFunctionBegin; 6363 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6364 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6365 PetscValidType(mat, 1); 6366 PetscValidType(is, 2); 6367 PetscCall(ISGetLocalSize(is, &numRows)); 6368 PetscCall(ISGetIndices(is, &rows)); 6369 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6370 PetscCall(ISRestoreIndices(is, &rows)); 6371 PetscFunctionReturn(PETSC_SUCCESS); 6372 } 6373 6374 /*@ 6375 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6376 of a set of rows of a matrix. 6377 6378 Collective 6379 6380 Input Parameters: 6381 + mat - the matrix 6382 . numRows - the number of rows to zero 6383 . rows - the global row indices 6384 . diag - value put in the diagonal of the zeroed rows 6385 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6386 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6387 6388 Level: intermediate 6389 6390 Notes: 6391 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6392 6393 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6394 6395 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6396 Krylov method to take advantage of the known solution on the zeroed rows. 6397 6398 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) 6399 from the matrix. 6400 6401 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6402 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6403 formats this does not alter the nonzero structure. 6404 6405 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6406 of the matrix is not changed the values are 6407 merely zeroed. 6408 6409 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6410 formats can optionally remove the main diagonal entry from the 6411 nonzero structure as well, by passing 0.0 as the final argument). 6412 6413 For the parallel case, all processes that share the matrix (i.e., 6414 those in the communicator used for matrix creation) MUST call this 6415 routine, regardless of whether any rows being zeroed are owned by 6416 them. 6417 6418 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6419 list only rows local to itself). 6420 6421 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6422 owns that are to be zeroed. This saves a global synchronization in the implementation. 6423 6424 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6425 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6426 @*/ 6427 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6428 { 6429 PetscFunctionBegin; 6430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6431 PetscValidType(mat, 1); 6432 if (numRows) PetscAssertPointer(rows, 3); 6433 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6434 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6435 MatCheckPreallocated(mat, 1); 6436 6437 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6438 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6439 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6440 PetscFunctionReturn(PETSC_SUCCESS); 6441 } 6442 6443 /*@ 6444 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6445 of a set of rows of a matrix indicated by an `IS` 6446 6447 Collective 6448 6449 Input Parameters: 6450 + mat - the matrix 6451 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6452 . diag - value put in all diagonals of eliminated rows 6453 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6454 - b - optional vector of right-hand side, that will be adjusted by provided solution 6455 6456 Level: intermediate 6457 6458 Note: 6459 See `MatZeroRows()` for details on how this routine operates. 6460 6461 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6462 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6463 @*/ 6464 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6465 { 6466 PetscInt numRows = 0; 6467 const PetscInt *rows = NULL; 6468 6469 PetscFunctionBegin; 6470 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6471 PetscValidType(mat, 1); 6472 if (is) { 6473 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6474 PetscCall(ISGetLocalSize(is, &numRows)); 6475 PetscCall(ISGetIndices(is, &rows)); 6476 } 6477 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6478 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6479 PetscFunctionReturn(PETSC_SUCCESS); 6480 } 6481 6482 /*@ 6483 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6484 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6485 6486 Collective 6487 6488 Input Parameters: 6489 + mat - the matrix 6490 . numRows - the number of rows to remove 6491 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6492 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6493 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6494 - b - optional vector of right-hand side, that will be adjusted by provided solution 6495 6496 Level: intermediate 6497 6498 Notes: 6499 See `MatZeroRows()` for details on how this routine operates. 6500 6501 The grid coordinates are across the entire grid, not just the local portion 6502 6503 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6504 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6505 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6506 `DM_BOUNDARY_PERIODIC` boundary type. 6507 6508 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 6509 a single value per point) you can skip filling those indices. 6510 6511 Fortran Note: 6512 `idxm` and `idxn` should be declared as 6513 $ MatStencil idxm(4, m) 6514 and the values inserted using 6515 .vb 6516 idxm(MatStencil_i, 1) = i 6517 idxm(MatStencil_j, 1) = j 6518 idxm(MatStencil_k, 1) = k 6519 idxm(MatStencil_c, 1) = c 6520 etc 6521 .ve 6522 6523 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6524 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6525 @*/ 6526 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6527 { 6528 PetscInt dim = mat->stencil.dim; 6529 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6530 PetscInt *dims = mat->stencil.dims + 1; 6531 PetscInt *starts = mat->stencil.starts; 6532 PetscInt *dxm = (PetscInt *)rows; 6533 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6534 6535 PetscFunctionBegin; 6536 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6537 PetscValidType(mat, 1); 6538 if (numRows) PetscAssertPointer(rows, 3); 6539 6540 PetscCall(PetscMalloc1(numRows, &jdxm)); 6541 for (i = 0; i < numRows; ++i) { 6542 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6543 for (j = 0; j < 3 - sdim; ++j) dxm++; 6544 /* Local index in X dir */ 6545 tmp = *dxm++ - starts[0]; 6546 /* Loop over remaining dimensions */ 6547 for (j = 0; j < dim - 1; ++j) { 6548 /* If nonlocal, set index to be negative */ 6549 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6550 /* Update local index */ 6551 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6552 } 6553 /* Skip component slot if necessary */ 6554 if (mat->stencil.noc) dxm++; 6555 /* Local row number */ 6556 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6557 } 6558 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6559 PetscCall(PetscFree(jdxm)); 6560 PetscFunctionReturn(PETSC_SUCCESS); 6561 } 6562 6563 /*@ 6564 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6565 of a set of rows and columns of a matrix. 6566 6567 Collective 6568 6569 Input Parameters: 6570 + mat - the matrix 6571 . numRows - the number of rows/columns to remove 6572 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6573 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6574 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6575 - b - optional vector of right-hand side, that will be adjusted by provided solution 6576 6577 Level: intermediate 6578 6579 Notes: 6580 See `MatZeroRowsColumns()` for details on how this routine operates. 6581 6582 The grid coordinates are across the entire grid, not just the local portion 6583 6584 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6585 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6586 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6587 `DM_BOUNDARY_PERIODIC` boundary type. 6588 6589 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 6590 a single value per point) you can skip filling those indices. 6591 6592 Fortran Note: 6593 `idxm` and `idxn` should be declared as 6594 $ MatStencil idxm(4, m) 6595 and the values inserted using 6596 .vb 6597 idxm(MatStencil_i, 1) = i 6598 idxm(MatStencil_j, 1) = j 6599 idxm(MatStencil_k, 1) = k 6600 idxm(MatStencil_c, 1) = c 6601 etc 6602 .ve 6603 6604 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6605 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6606 @*/ 6607 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6608 { 6609 PetscInt dim = mat->stencil.dim; 6610 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6611 PetscInt *dims = mat->stencil.dims + 1; 6612 PetscInt *starts = mat->stencil.starts; 6613 PetscInt *dxm = (PetscInt *)rows; 6614 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6615 6616 PetscFunctionBegin; 6617 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6618 PetscValidType(mat, 1); 6619 if (numRows) PetscAssertPointer(rows, 3); 6620 6621 PetscCall(PetscMalloc1(numRows, &jdxm)); 6622 for (i = 0; i < numRows; ++i) { 6623 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6624 for (j = 0; j < 3 - sdim; ++j) dxm++; 6625 /* Local index in X dir */ 6626 tmp = *dxm++ - starts[0]; 6627 /* Loop over remaining dimensions */ 6628 for (j = 0; j < dim - 1; ++j) { 6629 /* If nonlocal, set index to be negative */ 6630 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6631 /* Update local index */ 6632 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6633 } 6634 /* Skip component slot if necessary */ 6635 if (mat->stencil.noc) dxm++; 6636 /* Local row number */ 6637 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6638 } 6639 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6640 PetscCall(PetscFree(jdxm)); 6641 PetscFunctionReturn(PETSC_SUCCESS); 6642 } 6643 6644 /*@ 6645 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6646 of a set of rows of a matrix; using local numbering of rows. 6647 6648 Collective 6649 6650 Input Parameters: 6651 + mat - the matrix 6652 . numRows - the number of rows to remove 6653 . rows - the local row indices 6654 . diag - value put in all diagonals of eliminated rows 6655 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6656 - b - optional vector of right-hand side, that will be adjusted by provided solution 6657 6658 Level: intermediate 6659 6660 Notes: 6661 Before calling `MatZeroRowsLocal()`, the user must first set the 6662 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6663 6664 See `MatZeroRows()` for details on how this routine operates. 6665 6666 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6667 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6668 @*/ 6669 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6670 { 6671 PetscFunctionBegin; 6672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6673 PetscValidType(mat, 1); 6674 if (numRows) PetscAssertPointer(rows, 3); 6675 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6676 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6677 MatCheckPreallocated(mat, 1); 6678 6679 if (mat->ops->zerorowslocal) { 6680 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6681 } else { 6682 IS is, newis; 6683 const PetscInt *newRows; 6684 6685 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6686 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6687 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6688 PetscCall(ISGetIndices(newis, &newRows)); 6689 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6690 PetscCall(ISRestoreIndices(newis, &newRows)); 6691 PetscCall(ISDestroy(&newis)); 6692 PetscCall(ISDestroy(&is)); 6693 } 6694 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6695 PetscFunctionReturn(PETSC_SUCCESS); 6696 } 6697 6698 /*@ 6699 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6700 of a set of rows of a matrix; using local numbering of rows. 6701 6702 Collective 6703 6704 Input Parameters: 6705 + mat - the matrix 6706 . is - index set of rows to remove 6707 . diag - value put in all diagonals of eliminated rows 6708 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6709 - b - optional vector of right-hand side, that will be adjusted by provided solution 6710 6711 Level: intermediate 6712 6713 Notes: 6714 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6715 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6716 6717 See `MatZeroRows()` for details on how this routine operates. 6718 6719 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6720 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6721 @*/ 6722 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6723 { 6724 PetscInt numRows; 6725 const PetscInt *rows; 6726 6727 PetscFunctionBegin; 6728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6729 PetscValidType(mat, 1); 6730 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6731 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6733 MatCheckPreallocated(mat, 1); 6734 6735 PetscCall(ISGetLocalSize(is, &numRows)); 6736 PetscCall(ISGetIndices(is, &rows)); 6737 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6738 PetscCall(ISRestoreIndices(is, &rows)); 6739 PetscFunctionReturn(PETSC_SUCCESS); 6740 } 6741 6742 /*@ 6743 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6744 of a set of rows and columns of a matrix; using local numbering of rows. 6745 6746 Collective 6747 6748 Input Parameters: 6749 + mat - the matrix 6750 . numRows - the number of rows to remove 6751 . rows - the global row indices 6752 . diag - value put in all diagonals of eliminated rows 6753 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6754 - b - optional vector of right-hand side, that will be adjusted by provided solution 6755 6756 Level: intermediate 6757 6758 Notes: 6759 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6760 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6761 6762 See `MatZeroRowsColumns()` for details on how this routine operates. 6763 6764 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6765 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6766 @*/ 6767 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6768 { 6769 IS is, newis; 6770 const PetscInt *newRows; 6771 6772 PetscFunctionBegin; 6773 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6774 PetscValidType(mat, 1); 6775 if (numRows) PetscAssertPointer(rows, 3); 6776 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6777 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6778 MatCheckPreallocated(mat, 1); 6779 6780 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6781 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6782 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6783 PetscCall(ISGetIndices(newis, &newRows)); 6784 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6785 PetscCall(ISRestoreIndices(newis, &newRows)); 6786 PetscCall(ISDestroy(&newis)); 6787 PetscCall(ISDestroy(&is)); 6788 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6789 PetscFunctionReturn(PETSC_SUCCESS); 6790 } 6791 6792 /*@ 6793 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6794 of a set of rows and columns of a matrix; using local numbering of rows. 6795 6796 Collective 6797 6798 Input Parameters: 6799 + mat - the matrix 6800 . is - index set of rows to remove 6801 . diag - value put in all diagonals of eliminated rows 6802 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6803 - b - optional vector of right-hand side, that will be adjusted by provided solution 6804 6805 Level: intermediate 6806 6807 Notes: 6808 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6809 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6810 6811 See `MatZeroRowsColumns()` for details on how this routine operates. 6812 6813 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6814 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6815 @*/ 6816 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6817 { 6818 PetscInt numRows; 6819 const PetscInt *rows; 6820 6821 PetscFunctionBegin; 6822 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6823 PetscValidType(mat, 1); 6824 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6825 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6826 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6827 MatCheckPreallocated(mat, 1); 6828 6829 PetscCall(ISGetLocalSize(is, &numRows)); 6830 PetscCall(ISGetIndices(is, &rows)); 6831 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6832 PetscCall(ISRestoreIndices(is, &rows)); 6833 PetscFunctionReturn(PETSC_SUCCESS); 6834 } 6835 6836 /*@ 6837 MatGetSize - Returns the numbers of rows and columns in a matrix. 6838 6839 Not Collective 6840 6841 Input Parameter: 6842 . mat - the matrix 6843 6844 Output Parameters: 6845 + m - the number of global rows 6846 - n - the number of global columns 6847 6848 Level: beginner 6849 6850 Note: 6851 Both output parameters can be `NULL` on input. 6852 6853 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6854 @*/ 6855 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6856 { 6857 PetscFunctionBegin; 6858 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6859 if (m) *m = mat->rmap->N; 6860 if (n) *n = mat->cmap->N; 6861 PetscFunctionReturn(PETSC_SUCCESS); 6862 } 6863 6864 /*@ 6865 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6866 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6867 6868 Not Collective 6869 6870 Input Parameter: 6871 . mat - the matrix 6872 6873 Output Parameters: 6874 + m - the number of local rows, use `NULL` to not obtain this value 6875 - n - the number of local columns, use `NULL` to not obtain this value 6876 6877 Level: beginner 6878 6879 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6880 @*/ 6881 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6882 { 6883 PetscFunctionBegin; 6884 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6885 if (m) PetscAssertPointer(m, 2); 6886 if (n) PetscAssertPointer(n, 3); 6887 if (m) *m = mat->rmap->n; 6888 if (n) *n = mat->cmap->n; 6889 PetscFunctionReturn(PETSC_SUCCESS); 6890 } 6891 6892 /*@ 6893 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6894 vector one multiplies this matrix by that are owned by this processor. 6895 6896 Not Collective, unless matrix has not been allocated, then collective 6897 6898 Input Parameter: 6899 . mat - the matrix 6900 6901 Output Parameters: 6902 + m - the global index of the first local column, use `NULL` to not obtain this value 6903 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6904 6905 Level: developer 6906 6907 Notes: 6908 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6909 6910 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6911 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6912 6913 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6914 the local values in the matrix. 6915 6916 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6917 Layouts](sec_matlayout) for details on matrix layouts. 6918 6919 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6920 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6921 @*/ 6922 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6923 { 6924 PetscFunctionBegin; 6925 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6926 PetscValidType(mat, 1); 6927 if (m) PetscAssertPointer(m, 2); 6928 if (n) PetscAssertPointer(n, 3); 6929 MatCheckPreallocated(mat, 1); 6930 if (m) *m = mat->cmap->rstart; 6931 if (n) *n = mat->cmap->rend; 6932 PetscFunctionReturn(PETSC_SUCCESS); 6933 } 6934 6935 /*@ 6936 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6937 this MPI process. 6938 6939 Not Collective 6940 6941 Input Parameter: 6942 . mat - the matrix 6943 6944 Output Parameters: 6945 + m - the global index of the first local row, use `NULL` to not obtain this value 6946 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6947 6948 Level: beginner 6949 6950 Notes: 6951 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6952 6953 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6954 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6955 6956 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6957 the local values in the matrix. 6958 6959 The high argument is one more than the last element stored locally. 6960 6961 For all matrices it returns the range of matrix rows associated with rows of a vector that 6962 would contain the result of a matrix vector product with this matrix. See [Matrix 6963 Layouts](sec_matlayout) for details on matrix layouts. 6964 6965 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6966 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6967 @*/ 6968 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6969 { 6970 PetscFunctionBegin; 6971 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6972 PetscValidType(mat, 1); 6973 if (m) PetscAssertPointer(m, 2); 6974 if (n) PetscAssertPointer(n, 3); 6975 MatCheckPreallocated(mat, 1); 6976 if (m) *m = mat->rmap->rstart; 6977 if (n) *n = mat->rmap->rend; 6978 PetscFunctionReturn(PETSC_SUCCESS); 6979 } 6980 6981 /*@C 6982 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6983 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6984 6985 Not Collective, unless matrix has not been allocated 6986 6987 Input Parameter: 6988 . mat - the matrix 6989 6990 Output Parameter: 6991 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6992 where `size` is the number of MPI processes used by `mat` 6993 6994 Level: beginner 6995 6996 Notes: 6997 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6998 6999 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7000 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7001 7002 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7003 the local values in the matrix. 7004 7005 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 7006 would contain the result of a matrix vector product with this matrix. See [Matrix 7007 Layouts](sec_matlayout) for details on matrix layouts. 7008 7009 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 7010 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 7011 `DMDAGetGhostCorners()`, `DM` 7012 @*/ 7013 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 7014 { 7015 PetscFunctionBegin; 7016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7017 PetscValidType(mat, 1); 7018 MatCheckPreallocated(mat, 1); 7019 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 7020 PetscFunctionReturn(PETSC_SUCCESS); 7021 } 7022 7023 /*@C 7024 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 7025 vector one multiplies this vector by that are owned by each processor. 7026 7027 Not Collective, unless matrix has not been allocated 7028 7029 Input Parameter: 7030 . mat - the matrix 7031 7032 Output Parameter: 7033 . ranges - start of each processors portion plus one more than the total length at the end 7034 7035 Level: beginner 7036 7037 Notes: 7038 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7039 7040 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7041 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7042 7043 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7044 the local values in the matrix. 7045 7046 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7047 Layouts](sec_matlayout) for details on matrix layouts. 7048 7049 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7050 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7051 `DMDAGetGhostCorners()`, `DM` 7052 @*/ 7053 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7054 { 7055 PetscFunctionBegin; 7056 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7057 PetscValidType(mat, 1); 7058 MatCheckPreallocated(mat, 1); 7059 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7060 PetscFunctionReturn(PETSC_SUCCESS); 7061 } 7062 7063 /*@ 7064 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7065 7066 Not Collective 7067 7068 Input Parameter: 7069 . A - matrix 7070 7071 Output Parameters: 7072 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7073 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7074 7075 Level: intermediate 7076 7077 Note: 7078 You should call `ISDestroy()` on the returned `IS` 7079 7080 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7081 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7082 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7083 details on matrix layouts. 7084 7085 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7086 @*/ 7087 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7088 { 7089 PetscErrorCode (*f)(Mat, IS *, IS *); 7090 7091 PetscFunctionBegin; 7092 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7093 PetscValidType(A, 1); 7094 MatCheckPreallocated(A, 1); 7095 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7096 if (f) { 7097 PetscCall((*f)(A, rows, cols)); 7098 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7099 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7100 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7101 } 7102 PetscFunctionReturn(PETSC_SUCCESS); 7103 } 7104 7105 /*@ 7106 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7107 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7108 to complete the factorization. 7109 7110 Collective 7111 7112 Input Parameters: 7113 + fact - the factorized matrix obtained with `MatGetFactor()` 7114 . mat - the matrix 7115 . row - row permutation 7116 . col - column permutation 7117 - info - structure containing 7118 .vb 7119 levels - number of levels of fill. 7120 expected fill - as ratio of original fill. 7121 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7122 missing diagonal entries) 7123 .ve 7124 7125 Level: developer 7126 7127 Notes: 7128 See [Matrix Factorization](sec_matfactor) for additional information. 7129 7130 Most users should employ the `KSP` interface for linear solvers 7131 instead of working directly with matrix algebra routines such as this. 7132 See, e.g., `KSPCreate()`. 7133 7134 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7135 7136 Developer Note: 7137 The Fortran interface is not autogenerated as the 7138 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7139 7140 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7141 `MatGetOrdering()`, `MatFactorInfo` 7142 @*/ 7143 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7144 { 7145 PetscFunctionBegin; 7146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7147 PetscValidType(mat, 2); 7148 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7149 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7150 PetscAssertPointer(info, 5); 7151 PetscAssertPointer(fact, 1); 7152 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7153 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7154 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7155 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7156 MatCheckPreallocated(mat, 2); 7157 7158 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7159 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7160 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7161 PetscFunctionReturn(PETSC_SUCCESS); 7162 } 7163 7164 /*@ 7165 MatICCFactorSymbolic - Performs symbolic incomplete 7166 Cholesky factorization for a symmetric matrix. Use 7167 `MatCholeskyFactorNumeric()` to complete the factorization. 7168 7169 Collective 7170 7171 Input Parameters: 7172 + fact - the factorized matrix obtained with `MatGetFactor()` 7173 . mat - the matrix to be factored 7174 . perm - row and column permutation 7175 - info - structure containing 7176 .vb 7177 levels - number of levels of fill. 7178 expected fill - as ratio of original fill. 7179 .ve 7180 7181 Level: developer 7182 7183 Notes: 7184 Most users should employ the `KSP` interface for linear solvers 7185 instead of working directly with matrix algebra routines such as this. 7186 See, e.g., `KSPCreate()`. 7187 7188 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7189 7190 Developer Note: 7191 The Fortran interface is not autogenerated as the 7192 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7193 7194 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7195 @*/ 7196 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7197 { 7198 PetscFunctionBegin; 7199 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7200 PetscValidType(mat, 2); 7201 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7202 PetscAssertPointer(info, 4); 7203 PetscAssertPointer(fact, 1); 7204 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7205 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7206 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7207 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7208 MatCheckPreallocated(mat, 2); 7209 7210 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7211 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7212 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7213 PetscFunctionReturn(PETSC_SUCCESS); 7214 } 7215 7216 /*@C 7217 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7218 points to an array of valid matrices, they may be reused to store the new 7219 submatrices. 7220 7221 Collective 7222 7223 Input Parameters: 7224 + mat - the matrix 7225 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7226 . irow - index set of rows to extract 7227 . icol - index set of columns to extract 7228 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7229 7230 Output Parameter: 7231 . submat - the array of submatrices 7232 7233 Level: advanced 7234 7235 Notes: 7236 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7237 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7238 to extract a parallel submatrix. 7239 7240 Some matrix types place restrictions on the row and column 7241 indices, such as that they be sorted or that they be equal to each other. 7242 7243 The index sets may not have duplicate entries. 7244 7245 When extracting submatrices from a parallel matrix, each processor can 7246 form a different submatrix by setting the rows and columns of its 7247 individual index sets according to the local submatrix desired. 7248 7249 When finished using the submatrices, the user should destroy 7250 them with `MatDestroySubMatrices()`. 7251 7252 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7253 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7254 7255 This routine creates the matrices in submat; you should NOT create them before 7256 calling it. It also allocates the array of matrix pointers submat. 7257 7258 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7259 request one row/column in a block, they must request all rows/columns that are in 7260 that block. For example, if the block size is 2 you cannot request just row 0 and 7261 column 0. 7262 7263 Fortran Note: 7264 One must pass in as `submat` a `Mat` array of size at least `n`+1. 7265 7266 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7267 @*/ 7268 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7269 { 7270 PetscInt i; 7271 PetscBool eq; 7272 7273 PetscFunctionBegin; 7274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7275 PetscValidType(mat, 1); 7276 if (n) { 7277 PetscAssertPointer(irow, 3); 7278 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7279 PetscAssertPointer(icol, 4); 7280 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7281 } 7282 PetscAssertPointer(submat, 6); 7283 if (n && scall == MAT_REUSE_MATRIX) { 7284 PetscAssertPointer(*submat, 6); 7285 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7286 } 7287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7288 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7289 MatCheckPreallocated(mat, 1); 7290 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7291 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7292 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7293 for (i = 0; i < n; i++) { 7294 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7295 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7296 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7297 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7298 if (mat->boundtocpu && mat->bindingpropagates) { 7299 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7300 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7301 } 7302 #endif 7303 } 7304 PetscFunctionReturn(PETSC_SUCCESS); 7305 } 7306 7307 /*@C 7308 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms). 7309 7310 Collective 7311 7312 Input Parameters: 7313 + mat - the matrix 7314 . n - the number of submatrixes to be extracted 7315 . irow - index set of rows to extract 7316 . icol - index set of columns to extract 7317 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7318 7319 Output Parameter: 7320 . submat - the array of submatrices 7321 7322 Level: advanced 7323 7324 Note: 7325 This is used by `PCGASM` 7326 7327 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7328 @*/ 7329 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7330 { 7331 PetscInt i; 7332 PetscBool eq; 7333 7334 PetscFunctionBegin; 7335 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7336 PetscValidType(mat, 1); 7337 if (n) { 7338 PetscAssertPointer(irow, 3); 7339 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7340 PetscAssertPointer(icol, 4); 7341 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7342 } 7343 PetscAssertPointer(submat, 6); 7344 if (n && scall == MAT_REUSE_MATRIX) { 7345 PetscAssertPointer(*submat, 6); 7346 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7347 } 7348 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7349 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7350 MatCheckPreallocated(mat, 1); 7351 7352 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7353 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7354 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7355 for (i = 0; i < n; i++) { 7356 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7357 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7358 } 7359 PetscFunctionReturn(PETSC_SUCCESS); 7360 } 7361 7362 /*@C 7363 MatDestroyMatrices - Destroys an array of matrices. 7364 7365 Collective 7366 7367 Input Parameters: 7368 + n - the number of local matrices 7369 - mat - the matrices (this is a pointer to the array of matrices) 7370 7371 Level: advanced 7372 7373 Notes: 7374 Frees not only the matrices, but also the array that contains the matrices 7375 7376 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7377 7378 Fortran Note: 7379 Does not free the `mat` array. 7380 7381 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7382 @*/ 7383 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7384 { 7385 PetscInt i; 7386 7387 PetscFunctionBegin; 7388 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7389 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7390 PetscAssertPointer(mat, 2); 7391 7392 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7393 7394 /* memory is allocated even if n = 0 */ 7395 PetscCall(PetscFree(*mat)); 7396 PetscFunctionReturn(PETSC_SUCCESS); 7397 } 7398 7399 /*@C 7400 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7401 7402 Collective 7403 7404 Input Parameters: 7405 + n - the number of local matrices 7406 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling 7407 sequence of `MatCreateSubMatrices()`) 7408 7409 Level: advanced 7410 7411 Note: 7412 Frees not only the matrices, but also the array that contains the matrices 7413 7414 Fortran Note: 7415 Does not free the `mat` array. 7416 7417 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7418 @*/ 7419 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7420 { 7421 Mat mat0; 7422 7423 PetscFunctionBegin; 7424 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7425 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7426 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7427 PetscAssertPointer(mat, 2); 7428 7429 mat0 = (*mat)[0]; 7430 if (mat0 && mat0->ops->destroysubmatrices) { 7431 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7432 } else { 7433 PetscCall(MatDestroyMatrices(n, mat)); 7434 } 7435 PetscFunctionReturn(PETSC_SUCCESS); 7436 } 7437 7438 /*@ 7439 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7440 7441 Collective 7442 7443 Input Parameter: 7444 . mat - the matrix 7445 7446 Output Parameter: 7447 . matstruct - the sequential matrix with the nonzero structure of `mat` 7448 7449 Level: developer 7450 7451 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7452 @*/ 7453 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7454 { 7455 PetscFunctionBegin; 7456 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7457 PetscAssertPointer(matstruct, 2); 7458 7459 PetscValidType(mat, 1); 7460 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7461 MatCheckPreallocated(mat, 1); 7462 7463 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7464 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7465 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7466 PetscFunctionReturn(PETSC_SUCCESS); 7467 } 7468 7469 /*@C 7470 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7471 7472 Collective 7473 7474 Input Parameter: 7475 . mat - the matrix 7476 7477 Level: advanced 7478 7479 Note: 7480 This is not needed, one can just call `MatDestroy()` 7481 7482 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7483 @*/ 7484 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7485 { 7486 PetscFunctionBegin; 7487 PetscAssertPointer(mat, 1); 7488 PetscCall(MatDestroy(mat)); 7489 PetscFunctionReturn(PETSC_SUCCESS); 7490 } 7491 7492 /*@ 7493 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7494 replaces the index sets by larger ones that represent submatrices with 7495 additional overlap. 7496 7497 Collective 7498 7499 Input Parameters: 7500 + mat - the matrix 7501 . n - the number of index sets 7502 . is - the array of index sets (these index sets will changed during the call) 7503 - ov - the additional overlap requested 7504 7505 Options Database Key: 7506 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7507 7508 Level: developer 7509 7510 Note: 7511 The computed overlap preserves the matrix block sizes when the blocks are square. 7512 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7513 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7514 7515 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7516 @*/ 7517 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7518 { 7519 PetscInt i, bs, cbs; 7520 7521 PetscFunctionBegin; 7522 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7523 PetscValidType(mat, 1); 7524 PetscValidLogicalCollectiveInt(mat, n, 2); 7525 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7526 if (n) { 7527 PetscAssertPointer(is, 3); 7528 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7529 } 7530 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7531 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7532 MatCheckPreallocated(mat, 1); 7533 7534 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7535 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7536 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7537 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7538 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7539 if (bs == cbs) { 7540 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7541 } 7542 PetscFunctionReturn(PETSC_SUCCESS); 7543 } 7544 7545 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7546 7547 /*@ 7548 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7549 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7550 additional overlap. 7551 7552 Collective 7553 7554 Input Parameters: 7555 + mat - the matrix 7556 . n - the number of index sets 7557 . is - the array of index sets (these index sets will changed during the call) 7558 - ov - the additional overlap requested 7559 7560 ` Options Database Key: 7561 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7562 7563 Level: developer 7564 7565 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7566 @*/ 7567 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7568 { 7569 PetscInt i; 7570 7571 PetscFunctionBegin; 7572 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7573 PetscValidType(mat, 1); 7574 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7575 if (n) { 7576 PetscAssertPointer(is, 3); 7577 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7578 } 7579 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7580 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7581 MatCheckPreallocated(mat, 1); 7582 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7583 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7584 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7585 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7586 PetscFunctionReturn(PETSC_SUCCESS); 7587 } 7588 7589 /*@ 7590 MatGetBlockSize - Returns the matrix block size. 7591 7592 Not Collective 7593 7594 Input Parameter: 7595 . mat - the matrix 7596 7597 Output Parameter: 7598 . bs - block size 7599 7600 Level: intermediate 7601 7602 Notes: 7603 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7604 7605 If the block size has not been set yet this routine returns 1. 7606 7607 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7608 @*/ 7609 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7610 { 7611 PetscFunctionBegin; 7612 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7613 PetscAssertPointer(bs, 2); 7614 *bs = PetscAbs(mat->rmap->bs); 7615 PetscFunctionReturn(PETSC_SUCCESS); 7616 } 7617 7618 /*@ 7619 MatGetBlockSizes - Returns the matrix block row and column sizes. 7620 7621 Not Collective 7622 7623 Input Parameter: 7624 . mat - the matrix 7625 7626 Output Parameters: 7627 + rbs - row block size 7628 - cbs - column block size 7629 7630 Level: intermediate 7631 7632 Notes: 7633 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7634 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7635 7636 If a block size has not been set yet this routine returns 1. 7637 7638 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7639 @*/ 7640 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7641 { 7642 PetscFunctionBegin; 7643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7644 if (rbs) PetscAssertPointer(rbs, 2); 7645 if (cbs) PetscAssertPointer(cbs, 3); 7646 if (rbs) *rbs = PetscAbs(mat->rmap->bs); 7647 if (cbs) *cbs = PetscAbs(mat->cmap->bs); 7648 PetscFunctionReturn(PETSC_SUCCESS); 7649 } 7650 7651 /*@ 7652 MatSetBlockSize - Sets the matrix block size. 7653 7654 Logically Collective 7655 7656 Input Parameters: 7657 + mat - the matrix 7658 - bs - block size 7659 7660 Level: intermediate 7661 7662 Notes: 7663 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7664 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7665 7666 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7667 is compatible with the matrix local sizes. 7668 7669 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7670 @*/ 7671 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7672 { 7673 PetscFunctionBegin; 7674 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7675 PetscValidLogicalCollectiveInt(mat, bs, 2); 7676 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7677 PetscFunctionReturn(PETSC_SUCCESS); 7678 } 7679 7680 typedef struct { 7681 PetscInt n; 7682 IS *is; 7683 Mat *mat; 7684 PetscObjectState nonzerostate; 7685 Mat C; 7686 } EnvelopeData; 7687 7688 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7689 { 7690 EnvelopeData *edata = (EnvelopeData *)*ptr; 7691 7692 PetscFunctionBegin; 7693 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7694 PetscCall(PetscFree(edata->is)); 7695 PetscCall(PetscFree(edata)); 7696 PetscFunctionReturn(PETSC_SUCCESS); 7697 } 7698 7699 /*@ 7700 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7701 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7702 7703 Collective 7704 7705 Input Parameter: 7706 . mat - the matrix 7707 7708 Level: intermediate 7709 7710 Notes: 7711 There can be zeros within the blocks 7712 7713 The blocks can overlap between processes, including laying on more than two processes 7714 7715 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7716 @*/ 7717 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7718 { 7719 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7720 PetscInt *diag, *odiag, sc; 7721 VecScatter scatter; 7722 PetscScalar *seqv; 7723 const PetscScalar *parv; 7724 const PetscInt *ia, *ja; 7725 PetscBool set, flag, done; 7726 Mat AA = mat, A; 7727 MPI_Comm comm; 7728 PetscMPIInt rank, size, tag; 7729 MPI_Status status; 7730 PetscContainer container; 7731 EnvelopeData *edata; 7732 Vec seq, par; 7733 IS isglobal; 7734 7735 PetscFunctionBegin; 7736 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7737 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7738 if (!set || !flag) { 7739 /* TODO: only needs nonzero structure of transpose */ 7740 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7741 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7742 } 7743 PetscCall(MatAIJGetLocalMat(AA, &A)); 7744 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7745 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7746 7747 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7748 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7749 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7750 PetscCallMPI(MPI_Comm_size(comm, &size)); 7751 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7752 7753 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7754 7755 if (rank > 0) { 7756 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7757 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7758 } 7759 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7760 for (i = 0; i < n; i++) { 7761 env = PetscMax(env, ja[ia[i + 1] - 1]); 7762 II = rstart + i; 7763 if (env == II) { 7764 starts[lblocks] = tbs; 7765 sizes[lblocks++] = 1 + II - tbs; 7766 tbs = 1 + II; 7767 } 7768 } 7769 if (rank < size - 1) { 7770 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7771 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7772 } 7773 7774 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7775 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7776 PetscCall(MatDestroy(&A)); 7777 7778 PetscCall(PetscNew(&edata)); 7779 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7780 edata->n = lblocks; 7781 /* create IS needed for extracting blocks from the original matrix */ 7782 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7783 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7784 7785 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7786 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7787 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7788 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7789 PetscCall(MatSetType(edata->C, MATAIJ)); 7790 7791 /* Communicate the start and end of each row, from each block to the correct rank */ 7792 /* TODO: Use PetscSF instead of VecScatter */ 7793 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7794 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7795 PetscCall(VecGetArrayWrite(seq, &seqv)); 7796 for (PetscInt i = 0; i < lblocks; i++) { 7797 for (PetscInt j = 0; j < sizes[i]; j++) { 7798 seqv[cnt] = starts[i]; 7799 seqv[cnt + 1] = starts[i] + sizes[i]; 7800 cnt += 2; 7801 } 7802 } 7803 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7804 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7805 sc -= cnt; 7806 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7807 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7808 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7809 PetscCall(ISDestroy(&isglobal)); 7810 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7811 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7812 PetscCall(VecScatterDestroy(&scatter)); 7813 PetscCall(VecDestroy(&seq)); 7814 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7815 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7816 PetscCall(VecGetArrayRead(par, &parv)); 7817 cnt = 0; 7818 PetscCall(MatGetSize(mat, NULL, &n)); 7819 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7820 PetscInt start, end, d = 0, od = 0; 7821 7822 start = (PetscInt)PetscRealPart(parv[cnt]); 7823 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7824 cnt += 2; 7825 7826 if (start < cstart) { 7827 od += cstart - start + n - cend; 7828 d += cend - cstart; 7829 } else if (start < cend) { 7830 od += n - cend; 7831 d += cend - start; 7832 } else od += n - start; 7833 if (end <= cstart) { 7834 od -= cstart - end + n - cend; 7835 d -= cend - cstart; 7836 } else if (end < cend) { 7837 od -= n - cend; 7838 d -= cend - end; 7839 } else od -= n - end; 7840 7841 odiag[i] = od; 7842 diag[i] = d; 7843 } 7844 PetscCall(VecRestoreArrayRead(par, &parv)); 7845 PetscCall(VecDestroy(&par)); 7846 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7847 PetscCall(PetscFree2(diag, odiag)); 7848 PetscCall(PetscFree2(sizes, starts)); 7849 7850 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7851 PetscCall(PetscContainerSetPointer(container, edata)); 7852 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7853 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7854 PetscCall(PetscObjectDereference((PetscObject)container)); 7855 PetscFunctionReturn(PETSC_SUCCESS); 7856 } 7857 7858 /*@ 7859 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7860 7861 Collective 7862 7863 Input Parameters: 7864 + A - the matrix 7865 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7866 7867 Output Parameter: 7868 . C - matrix with inverted block diagonal of `A` 7869 7870 Level: advanced 7871 7872 Note: 7873 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7874 7875 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7876 @*/ 7877 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7878 { 7879 PetscContainer container; 7880 EnvelopeData *edata; 7881 PetscObjectState nonzerostate; 7882 7883 PetscFunctionBegin; 7884 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7885 if (!container) { 7886 PetscCall(MatComputeVariableBlockEnvelope(A)); 7887 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7888 } 7889 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7890 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7891 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7892 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7893 7894 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7895 *C = edata->C; 7896 7897 for (PetscInt i = 0; i < edata->n; i++) { 7898 Mat D; 7899 PetscScalar *dvalues; 7900 7901 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7902 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7903 PetscCall(MatSeqDenseInvert(D)); 7904 PetscCall(MatDenseGetArray(D, &dvalues)); 7905 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7906 PetscCall(MatDestroy(&D)); 7907 } 7908 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7909 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7910 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7911 PetscFunctionReturn(PETSC_SUCCESS); 7912 } 7913 7914 /*@ 7915 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7916 7917 Not Collective 7918 7919 Input Parameters: 7920 + mat - the matrix 7921 . nblocks - the number of blocks on this process, each block can only exist on a single process 7922 - bsizes - the block sizes 7923 7924 Level: intermediate 7925 7926 Notes: 7927 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7928 7929 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. 7930 7931 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7932 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7933 @*/ 7934 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7935 { 7936 PetscInt ncnt = 0, nlocal; 7937 7938 PetscFunctionBegin; 7939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7940 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7941 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); 7942 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7943 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); 7944 PetscCall(PetscFree(mat->bsizes)); 7945 mat->nblocks = nblocks; 7946 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7947 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7948 PetscFunctionReturn(PETSC_SUCCESS); 7949 } 7950 7951 /*@C 7952 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7953 7954 Not Collective; No Fortran Support 7955 7956 Input Parameter: 7957 . mat - the matrix 7958 7959 Output Parameters: 7960 + nblocks - the number of blocks on this process 7961 - bsizes - the block sizes 7962 7963 Level: intermediate 7964 7965 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7966 @*/ 7967 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7968 { 7969 PetscFunctionBegin; 7970 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7971 if (nblocks) *nblocks = mat->nblocks; 7972 if (bsizes) *bsizes = mat->bsizes; 7973 PetscFunctionReturn(PETSC_SUCCESS); 7974 } 7975 7976 /*@ 7977 MatSetBlockSizes - Sets the matrix block row and column sizes. 7978 7979 Logically Collective 7980 7981 Input Parameters: 7982 + mat - the matrix 7983 . rbs - row block size 7984 - cbs - column block size 7985 7986 Level: intermediate 7987 7988 Notes: 7989 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7990 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7991 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7992 7993 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7994 are compatible with the matrix local sizes. 7995 7996 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7997 7998 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7999 @*/ 8000 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8001 { 8002 PetscFunctionBegin; 8003 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8004 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8005 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8006 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8007 if (mat->rmap->refcnt) { 8008 ISLocalToGlobalMapping l2g = NULL; 8009 PetscLayout nmap = NULL; 8010 8011 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8012 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8013 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8014 mat->rmap = nmap; 8015 mat->rmap->mapping = l2g; 8016 } 8017 if (mat->cmap->refcnt) { 8018 ISLocalToGlobalMapping l2g = NULL; 8019 PetscLayout nmap = NULL; 8020 8021 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8022 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8023 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8024 mat->cmap = nmap; 8025 mat->cmap->mapping = l2g; 8026 } 8027 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8028 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8029 PetscFunctionReturn(PETSC_SUCCESS); 8030 } 8031 8032 /*@ 8033 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8034 8035 Logically Collective 8036 8037 Input Parameters: 8038 + mat - the matrix 8039 . fromRow - matrix from which to copy row block size 8040 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8041 8042 Level: developer 8043 8044 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8045 @*/ 8046 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8047 { 8048 PetscFunctionBegin; 8049 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8050 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8051 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8052 if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8053 if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8054 PetscFunctionReturn(PETSC_SUCCESS); 8055 } 8056 8057 /*@ 8058 MatResidual - Default routine to calculate the residual r = b - Ax 8059 8060 Collective 8061 8062 Input Parameters: 8063 + mat - the matrix 8064 . b - the right-hand-side 8065 - x - the approximate solution 8066 8067 Output Parameter: 8068 . r - location to store the residual 8069 8070 Level: developer 8071 8072 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8073 @*/ 8074 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8075 { 8076 PetscFunctionBegin; 8077 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8078 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8079 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8080 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8081 PetscValidType(mat, 1); 8082 MatCheckPreallocated(mat, 1); 8083 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8084 if (!mat->ops->residual) { 8085 PetscCall(MatMult(mat, x, r)); 8086 PetscCall(VecAYPX(r, -1.0, b)); 8087 } else { 8088 PetscUseTypeMethod(mat, residual, b, x, r); 8089 } 8090 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8091 PetscFunctionReturn(PETSC_SUCCESS); 8092 } 8093 8094 /*MC 8095 MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix 8096 8097 Synopsis: 8098 MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8099 8100 Not Collective 8101 8102 Input Parameters: 8103 + A - the matrix 8104 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8105 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8106 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8107 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8108 always used. 8109 8110 Output Parameters: 8111 + n - number of local rows in the (possibly compressed) matrix 8112 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8113 . ja - the column indices 8114 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8115 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8116 8117 Level: developer 8118 8119 Note: 8120 Use `MatRestoreRowIJF90()` when you no longer need access to the data 8121 8122 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()` 8123 M*/ 8124 8125 /*MC 8126 MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()` 8127 8128 Synopsis: 8129 MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr) 8130 8131 Not Collective 8132 8133 Input Parameters: 8134 + A - the matrix 8135 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8136 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8137 inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8138 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8139 always used. 8140 . n - number of local rows in the (possibly compressed) matrix 8141 . ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix 8142 . ja - the column indices 8143 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8144 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8145 8146 Level: developer 8147 8148 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()` 8149 M*/ 8150 8151 /*@C 8152 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8153 8154 Collective 8155 8156 Input Parameters: 8157 + mat - the matrix 8158 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8159 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8160 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8161 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8162 always used. 8163 8164 Output Parameters: 8165 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8166 . 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 8167 . ja - the column indices, use `NULL` if not needed 8168 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8169 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8170 8171 Level: developer 8172 8173 Notes: 8174 You CANNOT change any of the ia[] or ja[] values. 8175 8176 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8177 8178 Fortran Notes: 8179 Use 8180 .vb 8181 PetscInt, pointer :: ia(:),ja(:) 8182 call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8183 ! Access the ith and jth entries via ia(i) and ja(j) 8184 .ve 8185 8186 `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()` 8187 8188 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8189 @*/ 8190 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8191 { 8192 PetscFunctionBegin; 8193 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8194 PetscValidType(mat, 1); 8195 if (n) PetscAssertPointer(n, 5); 8196 if (ia) PetscAssertPointer(ia, 6); 8197 if (ja) PetscAssertPointer(ja, 7); 8198 if (done) PetscAssertPointer(done, 8); 8199 MatCheckPreallocated(mat, 1); 8200 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8201 else { 8202 if (done) *done = PETSC_TRUE; 8203 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8204 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8205 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8206 } 8207 PetscFunctionReturn(PETSC_SUCCESS); 8208 } 8209 8210 /*@C 8211 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8212 8213 Collective 8214 8215 Input Parameters: 8216 + mat - the matrix 8217 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8218 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8219 symmetrized 8220 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8221 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8222 always used. 8223 . n - number of columns in the (possibly compressed) matrix 8224 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8225 - ja - the row indices 8226 8227 Output Parameter: 8228 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8229 8230 Level: developer 8231 8232 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8233 @*/ 8234 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8235 { 8236 PetscFunctionBegin; 8237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8238 PetscValidType(mat, 1); 8239 PetscAssertPointer(n, 5); 8240 if (ia) PetscAssertPointer(ia, 6); 8241 if (ja) PetscAssertPointer(ja, 7); 8242 PetscAssertPointer(done, 8); 8243 MatCheckPreallocated(mat, 1); 8244 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8245 else { 8246 *done = PETSC_TRUE; 8247 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8248 } 8249 PetscFunctionReturn(PETSC_SUCCESS); 8250 } 8251 8252 /*@C 8253 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8254 8255 Collective 8256 8257 Input Parameters: 8258 + mat - the matrix 8259 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8260 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8261 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8262 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8263 always used. 8264 . n - size of (possibly compressed) matrix 8265 . ia - the row pointers 8266 - ja - the column indices 8267 8268 Output Parameter: 8269 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8270 8271 Level: developer 8272 8273 Note: 8274 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8275 us of the array after it has been restored. If you pass `NULL`, it will 8276 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8277 8278 Fortran Note: 8279 `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()` 8280 8281 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()` 8282 @*/ 8283 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8284 { 8285 PetscFunctionBegin; 8286 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8287 PetscValidType(mat, 1); 8288 if (ia) PetscAssertPointer(ia, 6); 8289 if (ja) PetscAssertPointer(ja, 7); 8290 if (done) PetscAssertPointer(done, 8); 8291 MatCheckPreallocated(mat, 1); 8292 8293 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8294 else { 8295 if (done) *done = PETSC_TRUE; 8296 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8297 if (n) *n = 0; 8298 if (ia) *ia = NULL; 8299 if (ja) *ja = NULL; 8300 } 8301 PetscFunctionReturn(PETSC_SUCCESS); 8302 } 8303 8304 /*@C 8305 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8306 8307 Collective 8308 8309 Input Parameters: 8310 + mat - the matrix 8311 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8312 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8313 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8314 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8315 always used. 8316 8317 Output Parameters: 8318 + n - size of (possibly compressed) matrix 8319 . ia - the column pointers 8320 . ja - the row indices 8321 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8322 8323 Level: developer 8324 8325 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8326 @*/ 8327 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8328 { 8329 PetscFunctionBegin; 8330 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8331 PetscValidType(mat, 1); 8332 if (ia) PetscAssertPointer(ia, 6); 8333 if (ja) PetscAssertPointer(ja, 7); 8334 PetscAssertPointer(done, 8); 8335 MatCheckPreallocated(mat, 1); 8336 8337 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8338 else { 8339 *done = PETSC_TRUE; 8340 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8341 if (n) *n = 0; 8342 if (ia) *ia = NULL; 8343 if (ja) *ja = NULL; 8344 } 8345 PetscFunctionReturn(PETSC_SUCCESS); 8346 } 8347 8348 /*@ 8349 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8350 `MatGetColumnIJ()`. 8351 8352 Collective 8353 8354 Input Parameters: 8355 + mat - the matrix 8356 . ncolors - maximum color value 8357 . n - number of entries in colorarray 8358 - colorarray - array indicating color for each column 8359 8360 Output Parameter: 8361 . iscoloring - coloring generated using colorarray information 8362 8363 Level: developer 8364 8365 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8366 @*/ 8367 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8368 { 8369 PetscFunctionBegin; 8370 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8371 PetscValidType(mat, 1); 8372 PetscAssertPointer(colorarray, 4); 8373 PetscAssertPointer(iscoloring, 5); 8374 MatCheckPreallocated(mat, 1); 8375 8376 if (!mat->ops->coloringpatch) { 8377 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8378 } else { 8379 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8380 } 8381 PetscFunctionReturn(PETSC_SUCCESS); 8382 } 8383 8384 /*@ 8385 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8386 8387 Logically Collective 8388 8389 Input Parameter: 8390 . mat - the factored matrix to be reset 8391 8392 Level: developer 8393 8394 Notes: 8395 This routine should be used only with factored matrices formed by in-place 8396 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8397 format). This option can save memory, for example, when solving nonlinear 8398 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8399 ILU(0) preconditioner. 8400 8401 One can specify in-place ILU(0) factorization by calling 8402 .vb 8403 PCType(pc,PCILU); 8404 PCFactorSeUseInPlace(pc); 8405 .ve 8406 or by using the options -pc_type ilu -pc_factor_in_place 8407 8408 In-place factorization ILU(0) can also be used as a local 8409 solver for the blocks within the block Jacobi or additive Schwarz 8410 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8411 for details on setting local solver options. 8412 8413 Most users should employ the `KSP` interface for linear solvers 8414 instead of working directly with matrix algebra routines such as this. 8415 See, e.g., `KSPCreate()`. 8416 8417 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8418 @*/ 8419 PetscErrorCode MatSetUnfactored(Mat mat) 8420 { 8421 PetscFunctionBegin; 8422 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8423 PetscValidType(mat, 1); 8424 MatCheckPreallocated(mat, 1); 8425 mat->factortype = MAT_FACTOR_NONE; 8426 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8427 PetscUseTypeMethod(mat, setunfactored); 8428 PetscFunctionReturn(PETSC_SUCCESS); 8429 } 8430 8431 /*MC 8432 MatDenseGetArrayF90 - Accesses a matrix array from Fortran 8433 8434 Synopsis: 8435 MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8436 8437 Not Collective 8438 8439 Input Parameter: 8440 . x - matrix 8441 8442 Output Parameters: 8443 + xx_v - the Fortran pointer to the array 8444 - ierr - error code 8445 8446 Example of Usage: 8447 .vb 8448 PetscScalar, pointer xx_v(:,:) 8449 .... 8450 call MatDenseGetArrayF90(x,xx_v,ierr) 8451 a = xx_v(3) 8452 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8453 .ve 8454 8455 Level: advanced 8456 8457 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()` 8458 M*/ 8459 8460 /*MC 8461 MatDenseRestoreArrayF90 - Restores a matrix array that has been 8462 accessed with `MatDenseGetArrayF90()`. 8463 8464 Synopsis: 8465 MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr) 8466 8467 Not Collective 8468 8469 Input Parameters: 8470 + x - matrix 8471 - xx_v - the Fortran90 pointer to the array 8472 8473 Output Parameter: 8474 . ierr - error code 8475 8476 Example of Usage: 8477 .vb 8478 PetscScalar, pointer xx_v(:,:) 8479 .... 8480 call MatDenseGetArrayF90(x,xx_v,ierr) 8481 a = xx_v(3) 8482 call MatDenseRestoreArrayF90(x,xx_v,ierr) 8483 .ve 8484 8485 Level: advanced 8486 8487 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()` 8488 M*/ 8489 8490 /*MC 8491 MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran. 8492 8493 Synopsis: 8494 MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8495 8496 Not Collective 8497 8498 Input Parameter: 8499 . x - matrix 8500 8501 Output Parameters: 8502 + xx_v - the Fortran pointer to the array 8503 - ierr - error code 8504 8505 Example of Usage: 8506 .vb 8507 PetscScalar, pointer xx_v(:) 8508 .... 8509 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8510 a = xx_v(3) 8511 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8512 .ve 8513 8514 Level: advanced 8515 8516 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()` 8517 M*/ 8518 8519 /*MC 8520 MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been 8521 accessed with `MatSeqAIJGetArrayF90()`. 8522 8523 Synopsis: 8524 MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr) 8525 8526 Not Collective 8527 8528 Input Parameters: 8529 + x - matrix 8530 - xx_v - the Fortran90 pointer to the array 8531 8532 Output Parameter: 8533 . ierr - error code 8534 8535 Example of Usage: 8536 .vb 8537 PetscScalar, pointer xx_v(:) 8538 .... 8539 call MatSeqAIJGetArrayF90(x,xx_v,ierr) 8540 a = xx_v(3) 8541 call MatSeqAIJRestoreArrayF90(x,xx_v,ierr) 8542 .ve 8543 8544 Level: advanced 8545 8546 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()` 8547 M*/ 8548 8549 /*@ 8550 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8551 as the original matrix. 8552 8553 Collective 8554 8555 Input Parameters: 8556 + mat - the original matrix 8557 . isrow - parallel `IS` containing the rows this processor should obtain 8558 . 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. 8559 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8560 8561 Output Parameter: 8562 . newmat - the new submatrix, of the same type as the original matrix 8563 8564 Level: advanced 8565 8566 Notes: 8567 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8568 8569 Some matrix types place restrictions on the row and column indices, such 8570 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; 8571 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8572 8573 The index sets may not have duplicate entries. 8574 8575 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8576 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8577 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8578 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8579 you are finished using it. 8580 8581 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8582 the input matrix. 8583 8584 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8585 8586 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8587 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8588 8589 Example usage: 8590 Consider the following 8x8 matrix with 34 non-zero values, that is 8591 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8592 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8593 as follows 8594 .vb 8595 1 2 0 | 0 3 0 | 0 4 8596 Proc0 0 5 6 | 7 0 0 | 8 0 8597 9 0 10 | 11 0 0 | 12 0 8598 ------------------------------------- 8599 13 0 14 | 15 16 17 | 0 0 8600 Proc1 0 18 0 | 19 20 21 | 0 0 8601 0 0 0 | 22 23 0 | 24 0 8602 ------------------------------------- 8603 Proc2 25 26 27 | 0 0 28 | 29 0 8604 30 0 0 | 31 32 33 | 0 34 8605 .ve 8606 8607 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8608 8609 .vb 8610 2 0 | 0 3 0 | 0 8611 Proc0 5 6 | 7 0 0 | 8 8612 ------------------------------- 8613 Proc1 18 0 | 19 20 21 | 0 8614 ------------------------------- 8615 Proc2 26 27 | 0 0 28 | 29 8616 0 0 | 31 32 33 | 0 8617 .ve 8618 8619 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8620 @*/ 8621 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8622 { 8623 PetscMPIInt size; 8624 Mat *local; 8625 IS iscoltmp; 8626 PetscBool flg; 8627 8628 PetscFunctionBegin; 8629 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8630 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8631 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8632 PetscAssertPointer(newmat, 5); 8633 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8634 PetscValidType(mat, 1); 8635 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8636 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8637 8638 MatCheckPreallocated(mat, 1); 8639 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8640 8641 if (!iscol || isrow == iscol) { 8642 PetscBool stride; 8643 PetscMPIInt grabentirematrix = 0, grab; 8644 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8645 if (stride) { 8646 PetscInt first, step, n, rstart, rend; 8647 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8648 if (step == 1) { 8649 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8650 if (rstart == first) { 8651 PetscCall(ISGetLocalSize(isrow, &n)); 8652 if (n == rend - rstart) grabentirematrix = 1; 8653 } 8654 } 8655 } 8656 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8657 if (grab) { 8658 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8659 if (cll == MAT_INITIAL_MATRIX) { 8660 *newmat = mat; 8661 PetscCall(PetscObjectReference((PetscObject)mat)); 8662 } 8663 PetscFunctionReturn(PETSC_SUCCESS); 8664 } 8665 } 8666 8667 if (!iscol) { 8668 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8669 } else { 8670 iscoltmp = iscol; 8671 } 8672 8673 /* if original matrix is on just one processor then use submatrix generated */ 8674 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8675 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8676 goto setproperties; 8677 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8678 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8679 *newmat = *local; 8680 PetscCall(PetscFree(local)); 8681 goto setproperties; 8682 } else if (!mat->ops->createsubmatrix) { 8683 /* Create a new matrix type that implements the operation using the full matrix */ 8684 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8685 switch (cll) { 8686 case MAT_INITIAL_MATRIX: 8687 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8688 break; 8689 case MAT_REUSE_MATRIX: 8690 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8691 break; 8692 default: 8693 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8694 } 8695 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8696 goto setproperties; 8697 } 8698 8699 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8700 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8701 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8702 8703 setproperties: 8704 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8705 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8706 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8707 } 8708 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8709 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8710 PetscFunctionReturn(PETSC_SUCCESS); 8711 } 8712 8713 /*@ 8714 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8715 8716 Not Collective 8717 8718 Input Parameters: 8719 + A - the matrix we wish to propagate options from 8720 - B - the matrix we wish to propagate options to 8721 8722 Level: beginner 8723 8724 Note: 8725 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8726 8727 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8728 @*/ 8729 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8730 { 8731 PetscFunctionBegin; 8732 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8733 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8734 B->symmetry_eternal = A->symmetry_eternal; 8735 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8736 B->symmetric = A->symmetric; 8737 B->structurally_symmetric = A->structurally_symmetric; 8738 B->spd = A->spd; 8739 B->hermitian = A->hermitian; 8740 PetscFunctionReturn(PETSC_SUCCESS); 8741 } 8742 8743 /*@ 8744 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8745 used during the assembly process to store values that belong to 8746 other processors. 8747 8748 Not Collective 8749 8750 Input Parameters: 8751 + mat - the matrix 8752 . size - the initial size of the stash. 8753 - bsize - the initial size of the block-stash(if used). 8754 8755 Options Database Keys: 8756 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8757 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8758 8759 Level: intermediate 8760 8761 Notes: 8762 The block-stash is used for values set with `MatSetValuesBlocked()` while 8763 the stash is used for values set with `MatSetValues()` 8764 8765 Run with the option -info and look for output of the form 8766 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8767 to determine the appropriate value, MM, to use for size and 8768 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8769 to determine the value, BMM to use for bsize 8770 8771 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8772 @*/ 8773 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8774 { 8775 PetscFunctionBegin; 8776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8777 PetscValidType(mat, 1); 8778 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8779 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8780 PetscFunctionReturn(PETSC_SUCCESS); 8781 } 8782 8783 /*@ 8784 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8785 the matrix 8786 8787 Neighbor-wise Collective 8788 8789 Input Parameters: 8790 + A - the matrix 8791 . x - the vector to be multiplied by the interpolation operator 8792 - y - the vector to be added to the result 8793 8794 Output Parameter: 8795 . w - the resulting vector 8796 8797 Level: intermediate 8798 8799 Notes: 8800 `w` may be the same vector as `y`. 8801 8802 This allows one to use either the restriction or interpolation (its transpose) 8803 matrix to do the interpolation 8804 8805 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8806 @*/ 8807 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8808 { 8809 PetscInt M, N, Ny; 8810 8811 PetscFunctionBegin; 8812 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8813 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8814 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8815 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8816 PetscCall(MatGetSize(A, &M, &N)); 8817 PetscCall(VecGetSize(y, &Ny)); 8818 if (M == Ny) { 8819 PetscCall(MatMultAdd(A, x, y, w)); 8820 } else { 8821 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8822 } 8823 PetscFunctionReturn(PETSC_SUCCESS); 8824 } 8825 8826 /*@ 8827 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8828 the matrix 8829 8830 Neighbor-wise Collective 8831 8832 Input Parameters: 8833 + A - the matrix 8834 - x - the vector to be interpolated 8835 8836 Output Parameter: 8837 . y - the resulting vector 8838 8839 Level: intermediate 8840 8841 Note: 8842 This allows one to use either the restriction or interpolation (its transpose) 8843 matrix to do the interpolation 8844 8845 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8846 @*/ 8847 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8848 { 8849 PetscInt M, N, Ny; 8850 8851 PetscFunctionBegin; 8852 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8853 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8854 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8855 PetscCall(MatGetSize(A, &M, &N)); 8856 PetscCall(VecGetSize(y, &Ny)); 8857 if (M == Ny) { 8858 PetscCall(MatMult(A, x, y)); 8859 } else { 8860 PetscCall(MatMultTranspose(A, x, y)); 8861 } 8862 PetscFunctionReturn(PETSC_SUCCESS); 8863 } 8864 8865 /*@ 8866 MatRestrict - $y = A*x$ or $A^T*x$ 8867 8868 Neighbor-wise Collective 8869 8870 Input Parameters: 8871 + A - the matrix 8872 - x - the vector to be restricted 8873 8874 Output Parameter: 8875 . y - the resulting vector 8876 8877 Level: intermediate 8878 8879 Note: 8880 This allows one to use either the restriction or interpolation (its transpose) 8881 matrix to do the restriction 8882 8883 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8884 @*/ 8885 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8886 { 8887 PetscInt M, N, Nx; 8888 8889 PetscFunctionBegin; 8890 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8891 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8892 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8893 PetscCall(MatGetSize(A, &M, &N)); 8894 PetscCall(VecGetSize(x, &Nx)); 8895 if (M == Nx) { 8896 PetscCall(MatMultTranspose(A, x, y)); 8897 } else { 8898 PetscCall(MatMult(A, x, y)); 8899 } 8900 PetscFunctionReturn(PETSC_SUCCESS); 8901 } 8902 8903 /*@ 8904 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8905 8906 Neighbor-wise Collective 8907 8908 Input Parameters: 8909 + A - the matrix 8910 . x - the input dense matrix to be multiplied 8911 - w - the input dense matrix to be added to the result 8912 8913 Output Parameter: 8914 . y - the output dense matrix 8915 8916 Level: intermediate 8917 8918 Note: 8919 This allows one to use either the restriction or interpolation (its transpose) 8920 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8921 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8922 8923 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8924 @*/ 8925 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8926 { 8927 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8928 PetscBool trans = PETSC_TRUE; 8929 MatReuse reuse = MAT_INITIAL_MATRIX; 8930 8931 PetscFunctionBegin; 8932 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8933 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8934 PetscValidType(x, 2); 8935 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8936 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8937 PetscCall(MatGetSize(A, &M, &N)); 8938 PetscCall(MatGetSize(x, &Mx, &Nx)); 8939 if (N == Mx) trans = PETSC_FALSE; 8940 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); 8941 Mo = trans ? N : M; 8942 if (*y) { 8943 PetscCall(MatGetSize(*y, &My, &Ny)); 8944 if (Mo == My && Nx == Ny) { 8945 reuse = MAT_REUSE_MATRIX; 8946 } else { 8947 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); 8948 PetscCall(MatDestroy(y)); 8949 } 8950 } 8951 8952 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8953 PetscBool flg; 8954 8955 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8956 if (w) { 8957 PetscInt My, Ny, Mw, Nw; 8958 8959 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8960 PetscCall(MatGetSize(*y, &My, &Ny)); 8961 PetscCall(MatGetSize(w, &Mw, &Nw)); 8962 if (!flg || My != Mw || Ny != Nw) w = NULL; 8963 } 8964 if (!w) { 8965 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8966 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8967 PetscCall(PetscObjectDereference((PetscObject)w)); 8968 } else { 8969 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8970 } 8971 } 8972 if (!trans) { 8973 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8974 } else { 8975 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8976 } 8977 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8978 PetscFunctionReturn(PETSC_SUCCESS); 8979 } 8980 8981 /*@ 8982 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8983 8984 Neighbor-wise Collective 8985 8986 Input Parameters: 8987 + A - the matrix 8988 - x - the input dense matrix 8989 8990 Output Parameter: 8991 . y - the output dense matrix 8992 8993 Level: intermediate 8994 8995 Note: 8996 This allows one to use either the restriction or interpolation (its transpose) 8997 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8998 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8999 9000 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 9001 @*/ 9002 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 9003 { 9004 PetscFunctionBegin; 9005 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9006 PetscFunctionReturn(PETSC_SUCCESS); 9007 } 9008 9009 /*@ 9010 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 9011 9012 Neighbor-wise Collective 9013 9014 Input Parameters: 9015 + A - the matrix 9016 - x - the input dense matrix 9017 9018 Output Parameter: 9019 . y - the output dense matrix 9020 9021 Level: intermediate 9022 9023 Note: 9024 This allows one to use either the restriction or interpolation (its transpose) 9025 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 9026 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 9027 9028 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 9029 @*/ 9030 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 9031 { 9032 PetscFunctionBegin; 9033 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 9034 PetscFunctionReturn(PETSC_SUCCESS); 9035 } 9036 9037 /*@ 9038 MatGetNullSpace - retrieves the null space of a matrix. 9039 9040 Logically Collective 9041 9042 Input Parameters: 9043 + mat - the matrix 9044 - nullsp - the null space object 9045 9046 Level: developer 9047 9048 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 9049 @*/ 9050 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 9051 { 9052 PetscFunctionBegin; 9053 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9054 PetscAssertPointer(nullsp, 2); 9055 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 9056 PetscFunctionReturn(PETSC_SUCCESS); 9057 } 9058 9059 /*@C 9060 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 9061 9062 Logically Collective 9063 9064 Input Parameters: 9065 + n - the number of matrices 9066 - mat - the array of matrices 9067 9068 Output Parameters: 9069 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 9070 9071 Level: developer 9072 9073 Note: 9074 Call `MatRestoreNullspaces()` to provide these to another array of matrices 9075 9076 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9077 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 9078 @*/ 9079 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9080 { 9081 PetscFunctionBegin; 9082 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9083 PetscAssertPointer(mat, 2); 9084 PetscAssertPointer(nullsp, 3); 9085 9086 PetscCall(PetscCalloc1(3 * n, nullsp)); 9087 for (PetscInt i = 0; i < n; i++) { 9088 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9089 (*nullsp)[i] = mat[i]->nullsp; 9090 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 9091 (*nullsp)[n + i] = mat[i]->nearnullsp; 9092 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 9093 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 9094 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 9095 } 9096 PetscFunctionReturn(PETSC_SUCCESS); 9097 } 9098 9099 /*@C 9100 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 9101 9102 Logically Collective 9103 9104 Input Parameters: 9105 + n - the number of matrices 9106 . mat - the array of matrices 9107 - nullsp - an array of null spaces 9108 9109 Level: developer 9110 9111 Note: 9112 Call `MatGetNullSpaces()` to create `nullsp` 9113 9114 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 9115 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 9116 @*/ 9117 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 9118 { 9119 PetscFunctionBegin; 9120 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9121 PetscAssertPointer(mat, 2); 9122 PetscAssertPointer(nullsp, 3); 9123 PetscAssertPointer(*nullsp, 3); 9124 9125 for (PetscInt i = 0; i < n; i++) { 9126 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9127 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9128 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9129 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9130 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9131 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9132 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9133 } 9134 PetscCall(PetscFree(*nullsp)); 9135 PetscFunctionReturn(PETSC_SUCCESS); 9136 } 9137 9138 /*@ 9139 MatSetNullSpace - attaches a null space to a matrix. 9140 9141 Logically Collective 9142 9143 Input Parameters: 9144 + mat - the matrix 9145 - nullsp - the null space object 9146 9147 Level: advanced 9148 9149 Notes: 9150 This null space is used by the `KSP` linear solvers to solve singular systems. 9151 9152 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` 9153 9154 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 9155 to zero but the linear system will still be solved in a least squares sense. 9156 9157 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9158 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)$. 9159 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 9160 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 9161 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$). 9162 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9163 9164 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 9165 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9166 routine also automatically calls `MatSetTransposeNullSpace()`. 9167 9168 The user should call `MatNullSpaceDestroy()`. 9169 9170 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9171 `KSPSetPCSide()` 9172 @*/ 9173 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9174 { 9175 PetscFunctionBegin; 9176 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9177 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9178 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9179 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9180 mat->nullsp = nullsp; 9181 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9182 PetscFunctionReturn(PETSC_SUCCESS); 9183 } 9184 9185 /*@ 9186 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9187 9188 Logically Collective 9189 9190 Input Parameters: 9191 + mat - the matrix 9192 - nullsp - the null space object 9193 9194 Level: developer 9195 9196 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9197 @*/ 9198 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9199 { 9200 PetscFunctionBegin; 9201 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9202 PetscValidType(mat, 1); 9203 PetscAssertPointer(nullsp, 2); 9204 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9205 PetscFunctionReturn(PETSC_SUCCESS); 9206 } 9207 9208 /*@ 9209 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9210 9211 Logically Collective 9212 9213 Input Parameters: 9214 + mat - the matrix 9215 - nullsp - the null space object 9216 9217 Level: advanced 9218 9219 Notes: 9220 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9221 9222 See `MatSetNullSpace()` 9223 9224 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9225 @*/ 9226 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9227 { 9228 PetscFunctionBegin; 9229 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9230 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9231 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9232 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9233 mat->transnullsp = nullsp; 9234 PetscFunctionReturn(PETSC_SUCCESS); 9235 } 9236 9237 /*@ 9238 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9239 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9240 9241 Logically Collective 9242 9243 Input Parameters: 9244 + mat - the matrix 9245 - nullsp - the null space object 9246 9247 Level: advanced 9248 9249 Notes: 9250 Overwrites any previous near null space that may have been attached 9251 9252 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9253 9254 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9255 @*/ 9256 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9257 { 9258 PetscFunctionBegin; 9259 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9260 PetscValidType(mat, 1); 9261 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9262 MatCheckPreallocated(mat, 1); 9263 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9264 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9265 mat->nearnullsp = nullsp; 9266 PetscFunctionReturn(PETSC_SUCCESS); 9267 } 9268 9269 /*@ 9270 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9271 9272 Not Collective 9273 9274 Input Parameter: 9275 . mat - the matrix 9276 9277 Output Parameter: 9278 . nullsp - the null space object, `NULL` if not set 9279 9280 Level: advanced 9281 9282 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9283 @*/ 9284 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9285 { 9286 PetscFunctionBegin; 9287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9288 PetscValidType(mat, 1); 9289 PetscAssertPointer(nullsp, 2); 9290 MatCheckPreallocated(mat, 1); 9291 *nullsp = mat->nearnullsp; 9292 PetscFunctionReturn(PETSC_SUCCESS); 9293 } 9294 9295 /*@ 9296 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9297 9298 Collective 9299 9300 Input Parameters: 9301 + mat - the matrix 9302 . row - row/column permutation 9303 - info - information on desired factorization process 9304 9305 Level: developer 9306 9307 Notes: 9308 Probably really in-place only when level of fill is zero, otherwise allocates 9309 new space to store factored matrix and deletes previous memory. 9310 9311 Most users should employ the `KSP` interface for linear solvers 9312 instead of working directly with matrix algebra routines such as this. 9313 See, e.g., `KSPCreate()`. 9314 9315 Developer Note: 9316 The Fortran interface is not autogenerated as the 9317 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9318 9319 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9320 @*/ 9321 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9322 { 9323 PetscFunctionBegin; 9324 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9325 PetscValidType(mat, 1); 9326 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9327 PetscAssertPointer(info, 3); 9328 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9329 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9330 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9331 MatCheckPreallocated(mat, 1); 9332 PetscUseTypeMethod(mat, iccfactor, row, info); 9333 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9334 PetscFunctionReturn(PETSC_SUCCESS); 9335 } 9336 9337 /*@ 9338 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9339 ghosted ones. 9340 9341 Not Collective 9342 9343 Input Parameters: 9344 + mat - the matrix 9345 - diag - the diagonal values, including ghost ones 9346 9347 Level: developer 9348 9349 Notes: 9350 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9351 9352 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9353 9354 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9355 @*/ 9356 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9357 { 9358 PetscMPIInt size; 9359 9360 PetscFunctionBegin; 9361 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9362 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9363 PetscValidType(mat, 1); 9364 9365 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9366 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9367 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9368 if (size == 1) { 9369 PetscInt n, m; 9370 PetscCall(VecGetSize(diag, &n)); 9371 PetscCall(MatGetSize(mat, NULL, &m)); 9372 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9373 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9374 } else { 9375 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9376 } 9377 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9378 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9379 PetscFunctionReturn(PETSC_SUCCESS); 9380 } 9381 9382 /*@ 9383 MatGetInertia - Gets the inertia from a factored matrix 9384 9385 Collective 9386 9387 Input Parameter: 9388 . mat - the matrix 9389 9390 Output Parameters: 9391 + nneg - number of negative eigenvalues 9392 . nzero - number of zero eigenvalues 9393 - npos - number of positive eigenvalues 9394 9395 Level: advanced 9396 9397 Note: 9398 Matrix must have been factored by `MatCholeskyFactor()` 9399 9400 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9401 @*/ 9402 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9403 { 9404 PetscFunctionBegin; 9405 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9406 PetscValidType(mat, 1); 9407 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9408 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9409 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9410 PetscFunctionReturn(PETSC_SUCCESS); 9411 } 9412 9413 /*@C 9414 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9415 9416 Neighbor-wise Collective 9417 9418 Input Parameters: 9419 + mat - the factored matrix obtained with `MatGetFactor()` 9420 - b - the right-hand-side vectors 9421 9422 Output Parameter: 9423 . x - the result vectors 9424 9425 Level: developer 9426 9427 Note: 9428 The vectors `b` and `x` cannot be the same. I.e., one cannot 9429 call `MatSolves`(A,x,x). 9430 9431 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9432 @*/ 9433 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9434 { 9435 PetscFunctionBegin; 9436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9437 PetscValidType(mat, 1); 9438 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9439 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9440 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9441 9442 MatCheckPreallocated(mat, 1); 9443 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9444 PetscUseTypeMethod(mat, solves, b, x); 9445 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9446 PetscFunctionReturn(PETSC_SUCCESS); 9447 } 9448 9449 /*@ 9450 MatIsSymmetric - Test whether a matrix is symmetric 9451 9452 Collective 9453 9454 Input Parameters: 9455 + A - the matrix to test 9456 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9457 9458 Output Parameter: 9459 . flg - the result 9460 9461 Level: intermediate 9462 9463 Notes: 9464 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9465 9466 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9467 9468 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9469 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9470 9471 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9472 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9473 @*/ 9474 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9475 { 9476 PetscFunctionBegin; 9477 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9478 PetscAssertPointer(flg, 3); 9479 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9480 else { 9481 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9482 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9483 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9484 } 9485 PetscFunctionReturn(PETSC_SUCCESS); 9486 } 9487 9488 /*@ 9489 MatIsHermitian - Test whether a matrix is Hermitian 9490 9491 Collective 9492 9493 Input Parameters: 9494 + A - the matrix to test 9495 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9496 9497 Output Parameter: 9498 . flg - the result 9499 9500 Level: intermediate 9501 9502 Notes: 9503 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9504 9505 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9506 9507 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9508 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9509 9510 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9511 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9512 @*/ 9513 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9514 { 9515 PetscFunctionBegin; 9516 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9517 PetscAssertPointer(flg, 3); 9518 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9519 else { 9520 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9521 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9522 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9523 } 9524 PetscFunctionReturn(PETSC_SUCCESS); 9525 } 9526 9527 /*@ 9528 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9529 9530 Not Collective 9531 9532 Input Parameter: 9533 . A - the matrix to check 9534 9535 Output Parameters: 9536 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9537 - flg - the result (only valid if set is `PETSC_TRUE`) 9538 9539 Level: advanced 9540 9541 Notes: 9542 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9543 if you want it explicitly checked 9544 9545 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9546 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9547 9548 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9549 @*/ 9550 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9551 { 9552 PetscFunctionBegin; 9553 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9554 PetscAssertPointer(set, 2); 9555 PetscAssertPointer(flg, 3); 9556 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9557 *set = PETSC_TRUE; 9558 *flg = PetscBool3ToBool(A->symmetric); 9559 } else { 9560 *set = PETSC_FALSE; 9561 } 9562 PetscFunctionReturn(PETSC_SUCCESS); 9563 } 9564 9565 /*@ 9566 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9567 9568 Not Collective 9569 9570 Input Parameter: 9571 . A - the matrix to check 9572 9573 Output Parameters: 9574 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9575 - flg - the result (only valid if set is `PETSC_TRUE`) 9576 9577 Level: advanced 9578 9579 Notes: 9580 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9581 9582 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9583 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9584 9585 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9586 @*/ 9587 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9588 { 9589 PetscFunctionBegin; 9590 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9591 PetscAssertPointer(set, 2); 9592 PetscAssertPointer(flg, 3); 9593 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9594 *set = PETSC_TRUE; 9595 *flg = PetscBool3ToBool(A->spd); 9596 } else { 9597 *set = PETSC_FALSE; 9598 } 9599 PetscFunctionReturn(PETSC_SUCCESS); 9600 } 9601 9602 /*@ 9603 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9604 9605 Not Collective 9606 9607 Input Parameter: 9608 . A - the matrix to check 9609 9610 Output Parameters: 9611 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9612 - flg - the result (only valid if set is `PETSC_TRUE`) 9613 9614 Level: advanced 9615 9616 Notes: 9617 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9618 if you want it explicitly checked 9619 9620 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9621 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9622 9623 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9624 @*/ 9625 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9626 { 9627 PetscFunctionBegin; 9628 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9629 PetscAssertPointer(set, 2); 9630 PetscAssertPointer(flg, 3); 9631 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9632 *set = PETSC_TRUE; 9633 *flg = PetscBool3ToBool(A->hermitian); 9634 } else { 9635 *set = PETSC_FALSE; 9636 } 9637 PetscFunctionReturn(PETSC_SUCCESS); 9638 } 9639 9640 /*@ 9641 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9642 9643 Collective 9644 9645 Input Parameter: 9646 . A - the matrix to test 9647 9648 Output Parameter: 9649 . flg - the result 9650 9651 Level: intermediate 9652 9653 Notes: 9654 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9655 9656 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 9657 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9658 9659 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9660 @*/ 9661 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9662 { 9663 PetscFunctionBegin; 9664 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9665 PetscAssertPointer(flg, 2); 9666 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9667 *flg = PetscBool3ToBool(A->structurally_symmetric); 9668 } else { 9669 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9670 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9671 } 9672 PetscFunctionReturn(PETSC_SUCCESS); 9673 } 9674 9675 /*@ 9676 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9677 9678 Not Collective 9679 9680 Input Parameter: 9681 . A - the matrix to check 9682 9683 Output Parameters: 9684 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9685 - flg - the result (only valid if set is PETSC_TRUE) 9686 9687 Level: advanced 9688 9689 Notes: 9690 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 9691 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9692 9693 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9694 9695 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9696 @*/ 9697 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9698 { 9699 PetscFunctionBegin; 9700 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9701 PetscAssertPointer(set, 2); 9702 PetscAssertPointer(flg, 3); 9703 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9704 *set = PETSC_TRUE; 9705 *flg = PetscBool3ToBool(A->structurally_symmetric); 9706 } else { 9707 *set = PETSC_FALSE; 9708 } 9709 PetscFunctionReturn(PETSC_SUCCESS); 9710 } 9711 9712 /*@ 9713 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9714 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9715 9716 Not Collective 9717 9718 Input Parameter: 9719 . mat - the matrix 9720 9721 Output Parameters: 9722 + nstash - the size of the stash 9723 . reallocs - the number of additional mallocs incurred. 9724 . bnstash - the size of the block stash 9725 - breallocs - the number of additional mallocs incurred.in the block stash 9726 9727 Level: advanced 9728 9729 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9730 @*/ 9731 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9732 { 9733 PetscFunctionBegin; 9734 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9735 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9736 PetscFunctionReturn(PETSC_SUCCESS); 9737 } 9738 9739 /*@ 9740 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9741 parallel layout, `PetscLayout` for rows and columns 9742 9743 Collective 9744 9745 Input Parameter: 9746 . mat - the matrix 9747 9748 Output Parameters: 9749 + right - (optional) vector that the matrix can be multiplied against 9750 - left - (optional) vector that the matrix vector product can be stored in 9751 9752 Level: advanced 9753 9754 Notes: 9755 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()`. 9756 9757 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9758 9759 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9760 @*/ 9761 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9762 { 9763 PetscFunctionBegin; 9764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9765 PetscValidType(mat, 1); 9766 if (mat->ops->getvecs) { 9767 PetscUseTypeMethod(mat, getvecs, right, left); 9768 } else { 9769 if (right) { 9770 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9771 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9772 PetscCall(VecSetType(*right, mat->defaultvectype)); 9773 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9774 if (mat->boundtocpu && mat->bindingpropagates) { 9775 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9776 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9777 } 9778 #endif 9779 } 9780 if (left) { 9781 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9782 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9783 PetscCall(VecSetType(*left, mat->defaultvectype)); 9784 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9785 if (mat->boundtocpu && mat->bindingpropagates) { 9786 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9787 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9788 } 9789 #endif 9790 } 9791 } 9792 PetscFunctionReturn(PETSC_SUCCESS); 9793 } 9794 9795 /*@ 9796 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9797 with default values. 9798 9799 Not Collective 9800 9801 Input Parameter: 9802 . info - the `MatFactorInfo` data structure 9803 9804 Level: developer 9805 9806 Notes: 9807 The solvers are generally used through the `KSP` and `PC` objects, for example 9808 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9809 9810 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9811 9812 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9813 @*/ 9814 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9815 { 9816 PetscFunctionBegin; 9817 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9818 PetscFunctionReturn(PETSC_SUCCESS); 9819 } 9820 9821 /*@ 9822 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9823 9824 Collective 9825 9826 Input Parameters: 9827 + mat - the factored matrix 9828 - is - the index set defining the Schur indices (0-based) 9829 9830 Level: advanced 9831 9832 Notes: 9833 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9834 9835 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9836 9837 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9838 9839 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9840 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9841 @*/ 9842 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9843 { 9844 PetscErrorCode (*f)(Mat, IS); 9845 9846 PetscFunctionBegin; 9847 PetscValidType(mat, 1); 9848 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9849 PetscValidType(is, 2); 9850 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9851 PetscCheckSameComm(mat, 1, is, 2); 9852 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9853 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9854 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9855 PetscCall(MatDestroy(&mat->schur)); 9856 PetscCall((*f)(mat, is)); 9857 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9858 PetscFunctionReturn(PETSC_SUCCESS); 9859 } 9860 9861 /*@ 9862 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9863 9864 Logically Collective 9865 9866 Input Parameters: 9867 + F - the factored matrix obtained by calling `MatGetFactor()` 9868 . S - location where to return the Schur complement, can be `NULL` 9869 - status - the status of the Schur complement matrix, can be `NULL` 9870 9871 Level: advanced 9872 9873 Notes: 9874 You must call `MatFactorSetSchurIS()` before calling this routine. 9875 9876 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9877 9878 The routine provides a copy of the Schur matrix stored within the solver data structures. 9879 The caller must destroy the object when it is no longer needed. 9880 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9881 9882 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) 9883 9884 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9885 9886 Developer Note: 9887 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9888 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9889 9890 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9891 @*/ 9892 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9893 { 9894 PetscFunctionBegin; 9895 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9896 if (S) PetscAssertPointer(S, 2); 9897 if (status) PetscAssertPointer(status, 3); 9898 if (S) { 9899 PetscErrorCode (*f)(Mat, Mat *); 9900 9901 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9902 if (f) { 9903 PetscCall((*f)(F, S)); 9904 } else { 9905 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9906 } 9907 } 9908 if (status) *status = F->schur_status; 9909 PetscFunctionReturn(PETSC_SUCCESS); 9910 } 9911 9912 /*@ 9913 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9914 9915 Logically Collective 9916 9917 Input Parameters: 9918 + F - the factored matrix obtained by calling `MatGetFactor()` 9919 . S - location where to return the Schur complement, can be `NULL` 9920 - status - the status of the Schur complement matrix, can be `NULL` 9921 9922 Level: advanced 9923 9924 Notes: 9925 You must call `MatFactorSetSchurIS()` before calling this routine. 9926 9927 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9928 9929 The routine returns a the Schur Complement stored within the data structures of the solver. 9930 9931 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9932 9933 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9934 9935 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9936 9937 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9938 9939 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9940 @*/ 9941 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9942 { 9943 PetscFunctionBegin; 9944 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9945 if (S) { 9946 PetscAssertPointer(S, 2); 9947 *S = F->schur; 9948 } 9949 if (status) { 9950 PetscAssertPointer(status, 3); 9951 *status = F->schur_status; 9952 } 9953 PetscFunctionReturn(PETSC_SUCCESS); 9954 } 9955 9956 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9957 { 9958 Mat S = F->schur; 9959 9960 PetscFunctionBegin; 9961 switch (F->schur_status) { 9962 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9963 case MAT_FACTOR_SCHUR_INVERTED: 9964 if (S) { 9965 S->ops->solve = NULL; 9966 S->ops->matsolve = NULL; 9967 S->ops->solvetranspose = NULL; 9968 S->ops->matsolvetranspose = NULL; 9969 S->ops->solveadd = NULL; 9970 S->ops->solvetransposeadd = NULL; 9971 S->factortype = MAT_FACTOR_NONE; 9972 PetscCall(PetscFree(S->solvertype)); 9973 } 9974 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9975 break; 9976 default: 9977 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9978 } 9979 PetscFunctionReturn(PETSC_SUCCESS); 9980 } 9981 9982 /*@ 9983 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9984 9985 Logically Collective 9986 9987 Input Parameters: 9988 + F - the factored matrix obtained by calling `MatGetFactor()` 9989 . S - location where the Schur complement is stored 9990 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9991 9992 Level: advanced 9993 9994 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9995 @*/ 9996 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9997 { 9998 PetscFunctionBegin; 9999 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10000 if (S) { 10001 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 10002 *S = NULL; 10003 } 10004 F->schur_status = status; 10005 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 10006 PetscFunctionReturn(PETSC_SUCCESS); 10007 } 10008 10009 /*@ 10010 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 10011 10012 Logically Collective 10013 10014 Input Parameters: 10015 + F - the factored matrix obtained by calling `MatGetFactor()` 10016 . rhs - location where the right-hand side of the Schur complement system is stored 10017 - sol - location where the solution of the Schur complement system has to be returned 10018 10019 Level: advanced 10020 10021 Notes: 10022 The sizes of the vectors should match the size of the Schur complement 10023 10024 Must be called after `MatFactorSetSchurIS()` 10025 10026 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 10027 @*/ 10028 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 10029 { 10030 PetscFunctionBegin; 10031 PetscValidType(F, 1); 10032 PetscValidType(rhs, 2); 10033 PetscValidType(sol, 3); 10034 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10035 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10036 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10037 PetscCheckSameComm(F, 1, rhs, 2); 10038 PetscCheckSameComm(F, 1, sol, 3); 10039 PetscCall(MatFactorFactorizeSchurComplement(F)); 10040 switch (F->schur_status) { 10041 case MAT_FACTOR_SCHUR_FACTORED: 10042 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 10043 break; 10044 case MAT_FACTOR_SCHUR_INVERTED: 10045 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 10046 break; 10047 default: 10048 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10049 } 10050 PetscFunctionReturn(PETSC_SUCCESS); 10051 } 10052 10053 /*@ 10054 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 10055 10056 Logically Collective 10057 10058 Input Parameters: 10059 + F - the factored matrix obtained by calling `MatGetFactor()` 10060 . rhs - location where the right-hand side of the Schur complement system is stored 10061 - sol - location where the solution of the Schur complement system has to be returned 10062 10063 Level: advanced 10064 10065 Notes: 10066 The sizes of the vectors should match the size of the Schur complement 10067 10068 Must be called after `MatFactorSetSchurIS()` 10069 10070 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 10071 @*/ 10072 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 10073 { 10074 PetscFunctionBegin; 10075 PetscValidType(F, 1); 10076 PetscValidType(rhs, 2); 10077 PetscValidType(sol, 3); 10078 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10079 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 10080 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 10081 PetscCheckSameComm(F, 1, rhs, 2); 10082 PetscCheckSameComm(F, 1, sol, 3); 10083 PetscCall(MatFactorFactorizeSchurComplement(F)); 10084 switch (F->schur_status) { 10085 case MAT_FACTOR_SCHUR_FACTORED: 10086 PetscCall(MatSolve(F->schur, rhs, sol)); 10087 break; 10088 case MAT_FACTOR_SCHUR_INVERTED: 10089 PetscCall(MatMult(F->schur, rhs, sol)); 10090 break; 10091 default: 10092 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 10093 } 10094 PetscFunctionReturn(PETSC_SUCCESS); 10095 } 10096 10097 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 10098 #if PetscDefined(HAVE_CUDA) 10099 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 10100 #endif 10101 10102 /* Schur status updated in the interface */ 10103 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 10104 { 10105 Mat S = F->schur; 10106 10107 PetscFunctionBegin; 10108 if (S) { 10109 PetscMPIInt size; 10110 PetscBool isdense, isdensecuda; 10111 10112 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 10113 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 10114 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 10115 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 10116 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 10117 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 10118 if (isdense) { 10119 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10120 } else if (isdensecuda) { 10121 #if defined(PETSC_HAVE_CUDA) 10122 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10123 #endif 10124 } 10125 // HIP?????????????? 10126 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10127 } 10128 PetscFunctionReturn(PETSC_SUCCESS); 10129 } 10130 10131 /*@ 10132 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10133 10134 Logically Collective 10135 10136 Input Parameter: 10137 . F - the factored matrix obtained by calling `MatGetFactor()` 10138 10139 Level: advanced 10140 10141 Notes: 10142 Must be called after `MatFactorSetSchurIS()`. 10143 10144 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10145 10146 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10147 @*/ 10148 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10149 { 10150 PetscFunctionBegin; 10151 PetscValidType(F, 1); 10152 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10153 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10154 PetscCall(MatFactorFactorizeSchurComplement(F)); 10155 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10156 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10157 PetscFunctionReturn(PETSC_SUCCESS); 10158 } 10159 10160 /*@ 10161 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10162 10163 Logically Collective 10164 10165 Input Parameter: 10166 . F - the factored matrix obtained by calling `MatGetFactor()` 10167 10168 Level: advanced 10169 10170 Note: 10171 Must be called after `MatFactorSetSchurIS()` 10172 10173 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10174 @*/ 10175 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10176 { 10177 MatFactorInfo info; 10178 10179 PetscFunctionBegin; 10180 PetscValidType(F, 1); 10181 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10182 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10183 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10184 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10185 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10186 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10187 } else { 10188 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10189 } 10190 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10191 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10192 PetscFunctionReturn(PETSC_SUCCESS); 10193 } 10194 10195 /*@ 10196 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10197 10198 Neighbor-wise Collective 10199 10200 Input Parameters: 10201 + A - the matrix 10202 . P - the projection matrix 10203 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10204 - 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 10205 if the result is a dense matrix this is irrelevant 10206 10207 Output Parameter: 10208 . C - the product matrix 10209 10210 Level: intermediate 10211 10212 Notes: 10213 C will be created and must be destroyed by the user with `MatDestroy()`. 10214 10215 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10216 10217 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10218 10219 Developer Note: 10220 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10221 10222 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10223 @*/ 10224 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10225 { 10226 PetscFunctionBegin; 10227 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10228 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10229 10230 if (scall == MAT_INITIAL_MATRIX) { 10231 PetscCall(MatProductCreate(A, P, NULL, C)); 10232 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10233 PetscCall(MatProductSetAlgorithm(*C, "default")); 10234 PetscCall(MatProductSetFill(*C, fill)); 10235 10236 (*C)->product->api_user = PETSC_TRUE; 10237 PetscCall(MatProductSetFromOptions(*C)); 10238 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); 10239 PetscCall(MatProductSymbolic(*C)); 10240 } else { /* scall == MAT_REUSE_MATRIX */ 10241 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10242 } 10243 10244 PetscCall(MatProductNumeric(*C)); 10245 (*C)->symmetric = A->symmetric; 10246 (*C)->spd = A->spd; 10247 PetscFunctionReturn(PETSC_SUCCESS); 10248 } 10249 10250 /*@ 10251 MatRARt - Creates the matrix product $C = R * A * R^T$ 10252 10253 Neighbor-wise Collective 10254 10255 Input Parameters: 10256 + A - the matrix 10257 . R - the projection matrix 10258 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10259 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10260 if the result is a dense matrix this is irrelevant 10261 10262 Output Parameter: 10263 . C - the product matrix 10264 10265 Level: intermediate 10266 10267 Notes: 10268 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10269 10270 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10271 10272 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10273 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10274 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10275 We recommend using `MatPtAP()` when possible. 10276 10277 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10278 10279 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10280 @*/ 10281 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10282 { 10283 PetscFunctionBegin; 10284 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10285 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10286 10287 if (scall == MAT_INITIAL_MATRIX) { 10288 PetscCall(MatProductCreate(A, R, NULL, C)); 10289 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10290 PetscCall(MatProductSetAlgorithm(*C, "default")); 10291 PetscCall(MatProductSetFill(*C, fill)); 10292 10293 (*C)->product->api_user = PETSC_TRUE; 10294 PetscCall(MatProductSetFromOptions(*C)); 10295 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); 10296 PetscCall(MatProductSymbolic(*C)); 10297 } else { /* scall == MAT_REUSE_MATRIX */ 10298 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10299 } 10300 10301 PetscCall(MatProductNumeric(*C)); 10302 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10303 PetscFunctionReturn(PETSC_SUCCESS); 10304 } 10305 10306 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10307 { 10308 PetscBool flg = PETSC_TRUE; 10309 10310 PetscFunctionBegin; 10311 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10312 if (scall == MAT_INITIAL_MATRIX) { 10313 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10314 PetscCall(MatProductCreate(A, B, NULL, C)); 10315 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10316 PetscCall(MatProductSetFill(*C, fill)); 10317 } else { /* scall == MAT_REUSE_MATRIX */ 10318 Mat_Product *product = (*C)->product; 10319 10320 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10321 if (flg && product && product->type != ptype) { 10322 PetscCall(MatProductClear(*C)); 10323 product = NULL; 10324 } 10325 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10326 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10327 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10328 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10329 product = (*C)->product; 10330 product->fill = fill; 10331 product->clear = PETSC_TRUE; 10332 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10333 flg = PETSC_FALSE; 10334 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10335 } 10336 } 10337 if (flg) { 10338 (*C)->product->api_user = PETSC_TRUE; 10339 PetscCall(MatProductSetType(*C, ptype)); 10340 PetscCall(MatProductSetFromOptions(*C)); 10341 PetscCall(MatProductSymbolic(*C)); 10342 } 10343 PetscCall(MatProductNumeric(*C)); 10344 PetscFunctionReturn(PETSC_SUCCESS); 10345 } 10346 10347 /*@ 10348 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10349 10350 Neighbor-wise Collective 10351 10352 Input Parameters: 10353 + A - the left matrix 10354 . B - the right matrix 10355 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10356 - 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 10357 if the result is a dense matrix this is irrelevant 10358 10359 Output Parameter: 10360 . C - the product matrix 10361 10362 Notes: 10363 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10364 10365 `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 10366 call to this function with `MAT_INITIAL_MATRIX`. 10367 10368 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10369 10370 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`, 10371 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10372 10373 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10374 10375 Example of Usage: 10376 .vb 10377 MatProductCreate(A,B,NULL,&C); 10378 MatProductSetType(C,MATPRODUCT_AB); 10379 MatProductSymbolic(C); 10380 MatProductNumeric(C); // compute C=A * B 10381 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10382 MatProductNumeric(C); 10383 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10384 MatProductNumeric(C); 10385 .ve 10386 10387 Level: intermediate 10388 10389 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10390 @*/ 10391 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10392 { 10393 PetscFunctionBegin; 10394 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10395 PetscFunctionReturn(PETSC_SUCCESS); 10396 } 10397 10398 /*@ 10399 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10400 10401 Neighbor-wise Collective 10402 10403 Input Parameters: 10404 + A - the left matrix 10405 . B - the right matrix 10406 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10407 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10408 10409 Output Parameter: 10410 . C - the product matrix 10411 10412 Options Database Key: 10413 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10414 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10415 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10416 10417 Level: intermediate 10418 10419 Notes: 10420 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10421 10422 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10423 10424 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10425 actually needed. 10426 10427 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10428 and for pairs of `MATMPIDENSE` matrices. 10429 10430 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10431 10432 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10433 10434 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10435 @*/ 10436 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10437 { 10438 PetscFunctionBegin; 10439 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10440 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10441 PetscFunctionReturn(PETSC_SUCCESS); 10442 } 10443 10444 /*@ 10445 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10446 10447 Neighbor-wise Collective 10448 10449 Input Parameters: 10450 + A - the left matrix 10451 . B - the right matrix 10452 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10453 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10454 10455 Output Parameter: 10456 . C - the product matrix 10457 10458 Level: intermediate 10459 10460 Notes: 10461 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10462 10463 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10464 10465 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10466 10467 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10468 actually needed. 10469 10470 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10471 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10472 10473 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10474 10475 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10476 @*/ 10477 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10478 { 10479 PetscFunctionBegin; 10480 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10481 PetscFunctionReturn(PETSC_SUCCESS); 10482 } 10483 10484 /*@ 10485 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10486 10487 Neighbor-wise Collective 10488 10489 Input Parameters: 10490 + A - the left matrix 10491 . B - the middle matrix 10492 . C - the right matrix 10493 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10494 - 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 10495 if the result is a dense matrix this is irrelevant 10496 10497 Output Parameter: 10498 . D - the product matrix 10499 10500 Level: intermediate 10501 10502 Notes: 10503 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10504 10505 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10506 10507 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10508 10509 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10510 actually needed. 10511 10512 If you have many matrices with the same non-zero structure to multiply, you 10513 should use `MAT_REUSE_MATRIX` in all calls but the first 10514 10515 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10516 10517 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10518 @*/ 10519 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10520 { 10521 PetscFunctionBegin; 10522 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10523 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10524 10525 if (scall == MAT_INITIAL_MATRIX) { 10526 PetscCall(MatProductCreate(A, B, C, D)); 10527 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10528 PetscCall(MatProductSetAlgorithm(*D, "default")); 10529 PetscCall(MatProductSetFill(*D, fill)); 10530 10531 (*D)->product->api_user = PETSC_TRUE; 10532 PetscCall(MatProductSetFromOptions(*D)); 10533 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, 10534 ((PetscObject)C)->type_name); 10535 PetscCall(MatProductSymbolic(*D)); 10536 } else { /* user may change input matrices when REUSE */ 10537 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10538 } 10539 PetscCall(MatProductNumeric(*D)); 10540 PetscFunctionReturn(PETSC_SUCCESS); 10541 } 10542 10543 /*@ 10544 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10545 10546 Collective 10547 10548 Input Parameters: 10549 + mat - the matrix 10550 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10551 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10552 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10553 10554 Output Parameter: 10555 . matredundant - redundant matrix 10556 10557 Level: advanced 10558 10559 Notes: 10560 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10561 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10562 10563 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10564 calling it. 10565 10566 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10567 10568 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10569 @*/ 10570 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10571 { 10572 MPI_Comm comm; 10573 PetscMPIInt size; 10574 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10575 Mat_Redundant *redund = NULL; 10576 PetscSubcomm psubcomm = NULL; 10577 MPI_Comm subcomm_in = subcomm; 10578 Mat *matseq; 10579 IS isrow, iscol; 10580 PetscBool newsubcomm = PETSC_FALSE; 10581 10582 PetscFunctionBegin; 10583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10584 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10585 PetscAssertPointer(*matredundant, 5); 10586 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10587 } 10588 10589 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10590 if (size == 1 || nsubcomm == 1) { 10591 if (reuse == MAT_INITIAL_MATRIX) { 10592 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10593 } else { 10594 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"); 10595 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10596 } 10597 PetscFunctionReturn(PETSC_SUCCESS); 10598 } 10599 10600 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10601 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10602 MatCheckPreallocated(mat, 1); 10603 10604 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10605 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10606 /* create psubcomm, then get subcomm */ 10607 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10608 PetscCallMPI(MPI_Comm_size(comm, &size)); 10609 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10610 10611 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10612 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10613 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10614 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10615 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10616 newsubcomm = PETSC_TRUE; 10617 PetscCall(PetscSubcommDestroy(&psubcomm)); 10618 } 10619 10620 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10621 if (reuse == MAT_INITIAL_MATRIX) { 10622 mloc_sub = PETSC_DECIDE; 10623 nloc_sub = PETSC_DECIDE; 10624 if (bs < 1) { 10625 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10626 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10627 } else { 10628 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10629 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10630 } 10631 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10632 rstart = rend - mloc_sub; 10633 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10634 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10635 PetscCall(ISSetIdentity(iscol)); 10636 } else { /* reuse == MAT_REUSE_MATRIX */ 10637 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"); 10638 /* retrieve subcomm */ 10639 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10640 redund = (*matredundant)->redundant; 10641 isrow = redund->isrow; 10642 iscol = redund->iscol; 10643 matseq = redund->matseq; 10644 } 10645 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10646 10647 /* get matredundant over subcomm */ 10648 if (reuse == MAT_INITIAL_MATRIX) { 10649 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10650 10651 /* create a supporting struct and attach it to C for reuse */ 10652 PetscCall(PetscNew(&redund)); 10653 (*matredundant)->redundant = redund; 10654 redund->isrow = isrow; 10655 redund->iscol = iscol; 10656 redund->matseq = matseq; 10657 if (newsubcomm) { 10658 redund->subcomm = subcomm; 10659 } else { 10660 redund->subcomm = MPI_COMM_NULL; 10661 } 10662 } else { 10663 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10664 } 10665 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10666 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10667 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10668 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10669 } 10670 #endif 10671 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10672 PetscFunctionReturn(PETSC_SUCCESS); 10673 } 10674 10675 /*@C 10676 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10677 a given `Mat`. Each submatrix can span multiple procs. 10678 10679 Collective 10680 10681 Input Parameters: 10682 + mat - the matrix 10683 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10684 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10685 10686 Output Parameter: 10687 . subMat - parallel sub-matrices each spanning a given `subcomm` 10688 10689 Level: advanced 10690 10691 Notes: 10692 The submatrix partition across processors is dictated by `subComm` a 10693 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10694 is not restricted to be grouped with consecutive original MPI processes. 10695 10696 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10697 map directly to the layout of the original matrix [wrt the local 10698 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10699 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10700 the `subMat`. However the offDiagMat looses some columns - and this is 10701 reconstructed with `MatSetValues()` 10702 10703 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10704 10705 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10706 @*/ 10707 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10708 { 10709 PetscMPIInt commsize, subCommSize; 10710 10711 PetscFunctionBegin; 10712 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10713 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10714 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10715 10716 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"); 10717 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10718 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10719 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10720 PetscFunctionReturn(PETSC_SUCCESS); 10721 } 10722 10723 /*@ 10724 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10725 10726 Not Collective 10727 10728 Input Parameters: 10729 + mat - matrix to extract local submatrix from 10730 . isrow - local row indices for submatrix 10731 - iscol - local column indices for submatrix 10732 10733 Output Parameter: 10734 . submat - the submatrix 10735 10736 Level: intermediate 10737 10738 Notes: 10739 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10740 10741 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10742 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10743 10744 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10745 `MatSetValuesBlockedLocal()` will also be implemented. 10746 10747 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10748 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10749 10750 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10751 @*/ 10752 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10753 { 10754 PetscFunctionBegin; 10755 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10756 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10757 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10758 PetscCheckSameComm(isrow, 2, iscol, 3); 10759 PetscAssertPointer(submat, 4); 10760 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10761 10762 if (mat->ops->getlocalsubmatrix) { 10763 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10764 } else { 10765 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10766 } 10767 PetscFunctionReturn(PETSC_SUCCESS); 10768 } 10769 10770 /*@ 10771 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10772 10773 Not Collective 10774 10775 Input Parameters: 10776 + mat - matrix to extract local submatrix from 10777 . isrow - local row indices for submatrix 10778 . iscol - local column indices for submatrix 10779 - submat - the submatrix 10780 10781 Level: intermediate 10782 10783 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10784 @*/ 10785 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10786 { 10787 PetscFunctionBegin; 10788 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10789 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10790 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10791 PetscCheckSameComm(isrow, 2, iscol, 3); 10792 PetscAssertPointer(submat, 4); 10793 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10794 10795 if (mat->ops->restorelocalsubmatrix) { 10796 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10797 } else { 10798 PetscCall(MatDestroy(submat)); 10799 } 10800 *submat = NULL; 10801 PetscFunctionReturn(PETSC_SUCCESS); 10802 } 10803 10804 /*@ 10805 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10806 10807 Collective 10808 10809 Input Parameter: 10810 . mat - the matrix 10811 10812 Output Parameter: 10813 . is - if any rows have zero diagonals this contains the list of them 10814 10815 Level: developer 10816 10817 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10818 @*/ 10819 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10820 { 10821 PetscFunctionBegin; 10822 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10823 PetscValidType(mat, 1); 10824 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10825 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10826 10827 if (!mat->ops->findzerodiagonals) { 10828 Vec diag; 10829 const PetscScalar *a; 10830 PetscInt *rows; 10831 PetscInt rStart, rEnd, r, nrow = 0; 10832 10833 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10834 PetscCall(MatGetDiagonal(mat, diag)); 10835 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10836 PetscCall(VecGetArrayRead(diag, &a)); 10837 for (r = 0; r < rEnd - rStart; ++r) 10838 if (a[r] == 0.0) ++nrow; 10839 PetscCall(PetscMalloc1(nrow, &rows)); 10840 nrow = 0; 10841 for (r = 0; r < rEnd - rStart; ++r) 10842 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10843 PetscCall(VecRestoreArrayRead(diag, &a)); 10844 PetscCall(VecDestroy(&diag)); 10845 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10846 } else { 10847 PetscUseTypeMethod(mat, findzerodiagonals, is); 10848 } 10849 PetscFunctionReturn(PETSC_SUCCESS); 10850 } 10851 10852 /*@ 10853 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10854 10855 Collective 10856 10857 Input Parameter: 10858 . mat - the matrix 10859 10860 Output Parameter: 10861 . is - contains the list of rows with off block diagonal entries 10862 10863 Level: developer 10864 10865 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10866 @*/ 10867 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10868 { 10869 PetscFunctionBegin; 10870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10871 PetscValidType(mat, 1); 10872 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10873 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10874 10875 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10876 PetscFunctionReturn(PETSC_SUCCESS); 10877 } 10878 10879 /*@C 10880 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10881 10882 Collective; No Fortran Support 10883 10884 Input Parameter: 10885 . mat - the matrix 10886 10887 Output Parameter: 10888 . values - the block inverses in column major order (FORTRAN-like) 10889 10890 Level: advanced 10891 10892 Notes: 10893 The size of the blocks is determined by the block size of the matrix. 10894 10895 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10896 10897 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10898 10899 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10900 @*/ 10901 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10902 { 10903 PetscFunctionBegin; 10904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10905 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10906 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10907 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10908 PetscFunctionReturn(PETSC_SUCCESS); 10909 } 10910 10911 /*@ 10912 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10913 10914 Collective; No Fortran Support 10915 10916 Input Parameters: 10917 + mat - the matrix 10918 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10919 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10920 10921 Output Parameter: 10922 . values - the block inverses in column major order (FORTRAN-like) 10923 10924 Level: advanced 10925 10926 Notes: 10927 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10928 10929 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10930 10931 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10932 @*/ 10933 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10934 { 10935 PetscFunctionBegin; 10936 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10937 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10938 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10939 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10940 PetscFunctionReturn(PETSC_SUCCESS); 10941 } 10942 10943 /*@ 10944 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10945 10946 Collective 10947 10948 Input Parameters: 10949 + A - the matrix 10950 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10951 10952 Level: advanced 10953 10954 Note: 10955 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10956 10957 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10958 @*/ 10959 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10960 { 10961 const PetscScalar *vals; 10962 PetscInt *dnnz; 10963 PetscInt m, rstart, rend, bs, i, j; 10964 10965 PetscFunctionBegin; 10966 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10967 PetscCall(MatGetBlockSize(A, &bs)); 10968 PetscCall(MatGetLocalSize(A, &m, NULL)); 10969 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10970 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10971 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10972 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10973 PetscCall(PetscFree(dnnz)); 10974 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10975 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10976 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10977 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10978 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10979 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10980 PetscFunctionReturn(PETSC_SUCCESS); 10981 } 10982 10983 /*@ 10984 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10985 via `MatTransposeColoringCreate()`. 10986 10987 Collective 10988 10989 Input Parameter: 10990 . c - coloring context 10991 10992 Level: intermediate 10993 10994 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10995 @*/ 10996 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10997 { 10998 MatTransposeColoring matcolor = *c; 10999 11000 PetscFunctionBegin; 11001 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 11002 if (--((PetscObject)matcolor)->refct > 0) { 11003 matcolor = NULL; 11004 PetscFunctionReturn(PETSC_SUCCESS); 11005 } 11006 11007 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 11008 PetscCall(PetscFree(matcolor->rows)); 11009 PetscCall(PetscFree(matcolor->den2sp)); 11010 PetscCall(PetscFree(matcolor->colorforcol)); 11011 PetscCall(PetscFree(matcolor->columns)); 11012 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 11013 PetscCall(PetscHeaderDestroy(c)); 11014 PetscFunctionReturn(PETSC_SUCCESS); 11015 } 11016 11017 /*@ 11018 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 11019 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 11020 `MatTransposeColoring` to sparse `B`. 11021 11022 Collective 11023 11024 Input Parameters: 11025 + coloring - coloring context created with `MatTransposeColoringCreate()` 11026 - B - sparse matrix 11027 11028 Output Parameter: 11029 . Btdense - dense matrix $B^T$ 11030 11031 Level: developer 11032 11033 Note: 11034 These are used internally for some implementations of `MatRARt()` 11035 11036 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 11037 @*/ 11038 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 11039 { 11040 PetscFunctionBegin; 11041 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11042 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 11043 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 11044 11045 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 11046 PetscFunctionReturn(PETSC_SUCCESS); 11047 } 11048 11049 /*@ 11050 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 11051 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 11052 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 11053 $C_{sp}$ from $C_{den}$. 11054 11055 Collective 11056 11057 Input Parameters: 11058 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 11059 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 11060 11061 Output Parameter: 11062 . Csp - sparse matrix 11063 11064 Level: developer 11065 11066 Note: 11067 These are used internally for some implementations of `MatRARt()` 11068 11069 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 11070 @*/ 11071 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 11072 { 11073 PetscFunctionBegin; 11074 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 11075 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 11076 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 11077 11078 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 11079 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 11080 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 11081 PetscFunctionReturn(PETSC_SUCCESS); 11082 } 11083 11084 /*@ 11085 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 11086 11087 Collective 11088 11089 Input Parameters: 11090 + mat - the matrix product C 11091 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 11092 11093 Output Parameter: 11094 . color - the new coloring context 11095 11096 Level: intermediate 11097 11098 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 11099 `MatTransColoringApplyDenToSp()` 11100 @*/ 11101 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 11102 { 11103 MatTransposeColoring c; 11104 MPI_Comm comm; 11105 11106 PetscFunctionBegin; 11107 PetscAssertPointer(color, 3); 11108 11109 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11110 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11111 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11112 c->ctype = iscoloring->ctype; 11113 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11114 *color = c; 11115 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11116 PetscFunctionReturn(PETSC_SUCCESS); 11117 } 11118 11119 /*@ 11120 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11121 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11122 11123 Not Collective 11124 11125 Input Parameter: 11126 . mat - the matrix 11127 11128 Output Parameter: 11129 . state - the current state 11130 11131 Level: intermediate 11132 11133 Notes: 11134 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11135 different matrices 11136 11137 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11138 11139 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11140 11141 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11142 @*/ 11143 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11144 { 11145 PetscFunctionBegin; 11146 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11147 *state = mat->nonzerostate; 11148 PetscFunctionReturn(PETSC_SUCCESS); 11149 } 11150 11151 /*@ 11152 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11153 matrices from each processor 11154 11155 Collective 11156 11157 Input Parameters: 11158 + comm - the communicators the parallel matrix will live on 11159 . seqmat - the input sequential matrices 11160 . n - number of local columns (or `PETSC_DECIDE`) 11161 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11162 11163 Output Parameter: 11164 . mpimat - the parallel matrix generated 11165 11166 Level: developer 11167 11168 Note: 11169 The number of columns of the matrix in EACH processor MUST be the same. 11170 11171 .seealso: [](ch_matrices), `Mat` 11172 @*/ 11173 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11174 { 11175 PetscMPIInt size; 11176 11177 PetscFunctionBegin; 11178 PetscCallMPI(MPI_Comm_size(comm, &size)); 11179 if (size == 1) { 11180 if (reuse == MAT_INITIAL_MATRIX) { 11181 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11182 } else { 11183 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11184 } 11185 PetscFunctionReturn(PETSC_SUCCESS); 11186 } 11187 11188 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"); 11189 11190 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11191 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11192 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11193 PetscFunctionReturn(PETSC_SUCCESS); 11194 } 11195 11196 /*@ 11197 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11198 11199 Collective 11200 11201 Input Parameters: 11202 + A - the matrix to create subdomains from 11203 - N - requested number of subdomains 11204 11205 Output Parameters: 11206 + n - number of subdomains resulting on this MPI process 11207 - iss - `IS` list with indices of subdomains on this MPI process 11208 11209 Level: advanced 11210 11211 Note: 11212 The number of subdomains must be smaller than the communicator size 11213 11214 .seealso: [](ch_matrices), `Mat`, `IS` 11215 @*/ 11216 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11217 { 11218 MPI_Comm comm, subcomm; 11219 PetscMPIInt size, rank, color; 11220 PetscInt rstart, rend, k; 11221 11222 PetscFunctionBegin; 11223 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11224 PetscCallMPI(MPI_Comm_size(comm, &size)); 11225 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11226 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); 11227 *n = 1; 11228 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11229 color = rank / k; 11230 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11231 PetscCall(PetscMalloc1(1, iss)); 11232 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11233 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11234 PetscCallMPI(MPI_Comm_free(&subcomm)); 11235 PetscFunctionReturn(PETSC_SUCCESS); 11236 } 11237 11238 /*@ 11239 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11240 11241 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11242 If they are not the same, uses `MatMatMatMult()`. 11243 11244 Once the coarse grid problem is constructed, correct for interpolation operators 11245 that are not of full rank, which can legitimately happen in the case of non-nested 11246 geometric multigrid. 11247 11248 Input Parameters: 11249 + restrct - restriction operator 11250 . dA - fine grid matrix 11251 . interpolate - interpolation operator 11252 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11253 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11254 11255 Output Parameter: 11256 . A - the Galerkin coarse matrix 11257 11258 Options Database Key: 11259 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11260 11261 Level: developer 11262 11263 Note: 11264 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11265 11266 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11267 @*/ 11268 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11269 { 11270 IS zerorows; 11271 Vec diag; 11272 11273 PetscFunctionBegin; 11274 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11275 /* Construct the coarse grid matrix */ 11276 if (interpolate == restrct) { 11277 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11278 } else { 11279 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11280 } 11281 11282 /* If the interpolation matrix is not of full rank, A will have zero rows. 11283 This can legitimately happen in the case of non-nested geometric multigrid. 11284 In that event, we set the rows of the matrix to the rows of the identity, 11285 ignoring the equations (as the RHS will also be zero). */ 11286 11287 PetscCall(MatFindZeroRows(*A, &zerorows)); 11288 11289 if (zerorows != NULL) { /* if there are any zero rows */ 11290 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11291 PetscCall(MatGetDiagonal(*A, diag)); 11292 PetscCall(VecISSet(diag, zerorows, 1.0)); 11293 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11294 PetscCall(VecDestroy(&diag)); 11295 PetscCall(ISDestroy(&zerorows)); 11296 } 11297 PetscFunctionReturn(PETSC_SUCCESS); 11298 } 11299 11300 /*@C 11301 MatSetOperation - Allows user to set a matrix operation for any matrix type 11302 11303 Logically Collective 11304 11305 Input Parameters: 11306 + mat - the matrix 11307 . op - the name of the operation 11308 - f - the function that provides the operation 11309 11310 Level: developer 11311 11312 Example Usage: 11313 .vb 11314 extern PetscErrorCode usermult(Mat, Vec, Vec); 11315 11316 PetscCall(MatCreateXXX(comm, ..., &A)); 11317 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11318 .ve 11319 11320 Notes: 11321 See the file `include/petscmat.h` for a complete list of matrix 11322 operations, which all have the form MATOP_<OPERATION>, where 11323 <OPERATION> is the name (in all capital letters) of the 11324 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11325 11326 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11327 sequence as the usual matrix interface routines, since they 11328 are intended to be accessed via the usual matrix interface 11329 routines, e.g., 11330 .vb 11331 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11332 .ve 11333 11334 In particular each function MUST return `PETSC_SUCCESS` on success and 11335 nonzero on failure. 11336 11337 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11338 11339 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11340 @*/ 11341 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11342 { 11343 PetscFunctionBegin; 11344 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11345 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11346 (((void (**)(void))mat->ops)[op]) = f; 11347 PetscFunctionReturn(PETSC_SUCCESS); 11348 } 11349 11350 /*@C 11351 MatGetOperation - Gets a matrix operation for any matrix type. 11352 11353 Not Collective 11354 11355 Input Parameters: 11356 + mat - the matrix 11357 - op - the name of the operation 11358 11359 Output Parameter: 11360 . f - the function that provides the operation 11361 11362 Level: developer 11363 11364 Example Usage: 11365 .vb 11366 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11367 11368 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11369 .ve 11370 11371 Notes: 11372 See the file include/petscmat.h for a complete list of matrix 11373 operations, which all have the form MATOP_<OPERATION>, where 11374 <OPERATION> is the name (in all capital letters) of the 11375 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11376 11377 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11378 11379 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11380 @*/ 11381 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11382 { 11383 PetscFunctionBegin; 11384 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11385 *f = (((void (**)(void))mat->ops)[op]); 11386 PetscFunctionReturn(PETSC_SUCCESS); 11387 } 11388 11389 /*@ 11390 MatHasOperation - Determines whether the given matrix supports the particular operation. 11391 11392 Not Collective 11393 11394 Input Parameters: 11395 + mat - the matrix 11396 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11397 11398 Output Parameter: 11399 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11400 11401 Level: advanced 11402 11403 Note: 11404 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11405 11406 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11407 @*/ 11408 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11409 { 11410 PetscFunctionBegin; 11411 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11412 PetscAssertPointer(has, 3); 11413 if (mat->ops->hasoperation) { 11414 PetscUseTypeMethod(mat, hasoperation, op, has); 11415 } else { 11416 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11417 else { 11418 *has = PETSC_FALSE; 11419 if (op == MATOP_CREATE_SUBMATRIX) { 11420 PetscMPIInt size; 11421 11422 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11423 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11424 } 11425 } 11426 } 11427 PetscFunctionReturn(PETSC_SUCCESS); 11428 } 11429 11430 /*@ 11431 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11432 11433 Collective 11434 11435 Input Parameter: 11436 . mat - the matrix 11437 11438 Output Parameter: 11439 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11440 11441 Level: beginner 11442 11443 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11444 @*/ 11445 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11446 { 11447 PetscFunctionBegin; 11448 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11449 PetscValidType(mat, 1); 11450 PetscAssertPointer(cong, 2); 11451 if (!mat->rmap || !mat->cmap) { 11452 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11453 PetscFunctionReturn(PETSC_SUCCESS); 11454 } 11455 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11456 PetscCall(PetscLayoutSetUp(mat->rmap)); 11457 PetscCall(PetscLayoutSetUp(mat->cmap)); 11458 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11459 if (*cong) mat->congruentlayouts = 1; 11460 else mat->congruentlayouts = 0; 11461 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11462 PetscFunctionReturn(PETSC_SUCCESS); 11463 } 11464 11465 PetscErrorCode MatSetInf(Mat A) 11466 { 11467 PetscFunctionBegin; 11468 PetscUseTypeMethod(A, setinf); 11469 PetscFunctionReturn(PETSC_SUCCESS); 11470 } 11471 11472 /*@ 11473 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 11474 and possibly removes small values from the graph structure. 11475 11476 Collective 11477 11478 Input Parameters: 11479 + A - the matrix 11480 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11481 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11482 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11483 . num_idx - size of 'index' array 11484 - index - array of block indices to use for graph strength of connection weight 11485 11486 Output Parameter: 11487 . graph - the resulting graph 11488 11489 Level: advanced 11490 11491 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11492 @*/ 11493 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11494 { 11495 PetscFunctionBegin; 11496 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11497 PetscValidType(A, 1); 11498 PetscValidLogicalCollectiveBool(A, scale, 3); 11499 PetscAssertPointer(graph, 7); 11500 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11501 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11502 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11503 PetscFunctionReturn(PETSC_SUCCESS); 11504 } 11505 11506 /*@ 11507 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11508 meaning the same memory is used for the matrix, and no new memory is allocated. 11509 11510 Collective 11511 11512 Input Parameters: 11513 + A - the matrix 11514 - 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 11515 11516 Level: intermediate 11517 11518 Developer Note: 11519 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11520 of the arrays in the data structure are unneeded. 11521 11522 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11523 @*/ 11524 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11525 { 11526 PetscFunctionBegin; 11527 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11528 PetscUseTypeMethod(A, eliminatezeros, keep); 11529 PetscFunctionReturn(PETSC_SUCCESS); 11530 } 11531