1 /* 2 This is where the abstract matrix operations are defined 3 Portions of this code are under: 4 Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved. 5 */ 6 7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 8 #include <petsc/private/isimpl.h> 9 #include <petsc/private/vecimpl.h> 10 11 /* Logging support */ 12 PetscClassId MAT_CLASSID; 13 PetscClassId MAT_COLORING_CLASSID; 14 PetscClassId MAT_FDCOLORING_CLASSID; 15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID; 16 17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose; 18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve; 19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic; 20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor; 21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin; 22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor; 23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure; 24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate; 25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat; 26 PetscLogEvent MAT_TransposeColoringCreate; 27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric; 28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric; 29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric; 30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric; 31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric; 32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd; 33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols; 34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym; 35 PetscLogEvent MAT_GetMultiProcBlock; 36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis; 37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis; 38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO; 39 PetscLogEvent MAT_CreateGraph; 40 PetscLogEvent MAT_SetValuesBatch; 41 PetscLogEvent MAT_ViennaCLCopyToGPU; 42 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU; 43 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU; 44 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom; 45 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS; 46 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights; 47 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR; 48 49 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL}; 50 51 /*@ 52 MatSetRandom - Sets all components of a matrix to random numbers. 53 54 Logically Collective 55 56 Input Parameters: 57 + x - the matrix 58 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and 59 it will create one internally. 60 61 Example: 62 .vb 63 PetscRandomCreate(PETSC_COMM_WORLD,&rctx); 64 MatSetRandom(x,rctx); 65 PetscRandomDestroy(rctx); 66 .ve 67 68 Level: intermediate 69 70 Notes: 71 For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations, 72 73 for sparse matrices that already have nonzero locations, it fills the locations with random numbers. 74 75 It generates an error if used on unassembled sparse matrices that have not been preallocated. 76 77 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()` 78 @*/ 79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) 80 { 81 PetscRandom randObj = NULL; 82 83 PetscFunctionBegin; 84 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 85 if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2); 86 PetscValidType(x, 1); 87 MatCheckPreallocated(x, 1); 88 89 if (!rctx) { 90 MPI_Comm comm; 91 PetscCall(PetscObjectGetComm((PetscObject)x, &comm)); 92 PetscCall(PetscRandomCreate(comm, &randObj)); 93 PetscCall(PetscRandomSetType(randObj, x->defaultrandtype)); 94 PetscCall(PetscRandomSetFromOptions(randObj)); 95 rctx = randObj; 96 } 97 PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0)); 98 PetscUseTypeMethod(x, setrandom, rctx); 99 PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0)); 100 101 PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY)); 102 PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY)); 103 PetscCall(PetscRandomDestroy(&randObj)); 104 PetscFunctionReturn(PETSC_SUCCESS); 105 } 106 107 /*@ 108 MatCopyHashToXAIJ - copy hash table entries into an XAIJ matrix type 109 110 Logically Collective 111 112 Input Parameter: 113 . A - A matrix in unassembled, hash table form 114 115 Output Parameter: 116 . B - The XAIJ matrix. This can either be `A` or some matrix of equivalent size, e.g. obtained from `A` via `MatDuplicate()` 117 118 Example: 119 .vb 120 PetscCall(MatDuplicate(A, MAT_DO_NOT_COPY_VALUES, &B)); 121 PetscCall(MatCopyHashToXAIJ(A, B)); 122 .ve 123 124 Level: advanced 125 126 Notes: 127 If `B` is `A`, then the hash table data structure will be destroyed. `B` is assembled 128 129 .seealso: [](ch_matrices), `Mat`, `MAT_USE_HASH_TABLE` 130 @*/ 131 PetscErrorCode MatCopyHashToXAIJ(Mat A, Mat B) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 135 PetscUseTypeMethod(A, copyhashtoxaij, B); 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 /*@ 140 MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in 141 142 Logically Collective 143 144 Input Parameter: 145 . mat - the factored matrix 146 147 Output Parameters: 148 + pivot - the pivot value computed 149 - row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes 150 the share the matrix 151 152 Level: advanced 153 154 Notes: 155 This routine does not work for factorizations done with external packages. 156 157 This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT` 158 159 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 160 161 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, 162 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, 163 `MAT_FACTOR_NUMERIC_ZEROPIVOT` 164 @*/ 165 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) 166 { 167 PetscFunctionBegin; 168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 169 PetscAssertPointer(pivot, 2); 170 PetscAssertPointer(row, 3); 171 *pivot = mat->factorerror_zeropivot_value; 172 *row = mat->factorerror_zeropivot_row; 173 PetscFunctionReturn(PETSC_SUCCESS); 174 } 175 176 /*@ 177 MatFactorGetError - gets the error code from a factorization 178 179 Logically Collective 180 181 Input Parameter: 182 . mat - the factored matrix 183 184 Output Parameter: 185 . err - the error code 186 187 Level: advanced 188 189 Note: 190 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 191 192 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, 193 `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError` 194 @*/ 195 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) 196 { 197 PetscFunctionBegin; 198 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 199 PetscAssertPointer(err, 2); 200 *err = mat->factorerrortype; 201 PetscFunctionReturn(PETSC_SUCCESS); 202 } 203 204 /*@ 205 MatFactorClearError - clears the error code in a factorization 206 207 Logically Collective 208 209 Input Parameter: 210 . mat - the factored matrix 211 212 Level: developer 213 214 Note: 215 This can also be called on non-factored matrices that come from, for example, matrices used in SOR. 216 217 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`, 218 `MatGetErrorCode()`, `MatFactorError` 219 @*/ 220 PetscErrorCode MatFactorClearError(Mat mat) 221 { 222 PetscFunctionBegin; 223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 224 mat->factorerrortype = MAT_FACTOR_NOERROR; 225 mat->factorerror_zeropivot_value = 0.0; 226 mat->factorerror_zeropivot_row = 0; 227 PetscFunctionReturn(PETSC_SUCCESS); 228 } 229 230 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) 231 { 232 Vec r, l; 233 const PetscScalar *al; 234 PetscInt i, nz, gnz, N, n, st; 235 236 PetscFunctionBegin; 237 PetscCall(MatCreateVecs(mat, &r, &l)); 238 if (!cols) { /* nonzero rows */ 239 PetscCall(MatGetOwnershipRange(mat, &st, NULL)); 240 PetscCall(MatGetSize(mat, &N, NULL)); 241 PetscCall(MatGetLocalSize(mat, &n, NULL)); 242 PetscCall(VecSet(l, 0.0)); 243 PetscCall(VecSetRandom(r, NULL)); 244 PetscCall(MatMult(mat, r, l)); 245 PetscCall(VecGetArrayRead(l, &al)); 246 } else { /* nonzero columns */ 247 PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL)); 248 PetscCall(MatGetSize(mat, NULL, &N)); 249 PetscCall(MatGetLocalSize(mat, NULL, &n)); 250 PetscCall(VecSet(r, 0.0)); 251 PetscCall(VecSetRandom(l, NULL)); 252 PetscCall(MatMultTranspose(mat, l, r)); 253 PetscCall(VecGetArrayRead(r, &al)); 254 } 255 if (tol <= 0.0) { 256 for (i = 0, nz = 0; i < n; i++) 257 if (al[i] != 0.0) nz++; 258 } else { 259 for (i = 0, nz = 0; i < n; i++) 260 if (PetscAbsScalar(al[i]) > tol) nz++; 261 } 262 PetscCallMPI(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 263 if (gnz != N) { 264 PetscInt *nzr; 265 PetscCall(PetscMalloc1(nz, &nzr)); 266 if (nz) { 267 if (tol < 0) { 268 for (i = 0, nz = 0; i < n; i++) 269 if (al[i] != 0.0) nzr[nz++] = i + st; 270 } else { 271 for (i = 0, nz = 0; i < n; i++) 272 if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st; 273 } 274 } 275 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero)); 276 } else *nonzero = NULL; 277 if (!cols) { /* nonzero rows */ 278 PetscCall(VecRestoreArrayRead(l, &al)); 279 } else { 280 PetscCall(VecRestoreArrayRead(r, &al)); 281 } 282 PetscCall(VecDestroy(&l)); 283 PetscCall(VecDestroy(&r)); 284 PetscFunctionReturn(PETSC_SUCCESS); 285 } 286 287 /*@ 288 MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix 289 290 Input Parameter: 291 . mat - the matrix 292 293 Output Parameter: 294 . keptrows - the rows that are not completely zero 295 296 Level: intermediate 297 298 Note: 299 `keptrows` is set to `NULL` if all rows are nonzero. 300 301 Developer Note: 302 If `keptrows` is not `NULL`, it must be sorted. 303 304 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()` 305 @*/ 306 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) 307 { 308 PetscFunctionBegin; 309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 310 PetscValidType(mat, 1); 311 PetscAssertPointer(keptrows, 2); 312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 314 if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows); 315 else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows)); 316 if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE)); 317 PetscFunctionReturn(PETSC_SUCCESS); 318 } 319 320 /*@ 321 MatFindZeroRows - Locate all rows that are completely zero in the matrix 322 323 Input Parameter: 324 . mat - the matrix 325 326 Output Parameter: 327 . zerorows - the rows that are completely zero 328 329 Level: intermediate 330 331 Note: 332 `zerorows` is set to `NULL` if no rows are zero. 333 334 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()` 335 @*/ 336 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) 337 { 338 IS keptrows; 339 PetscInt m, n; 340 341 PetscFunctionBegin; 342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 343 PetscValidType(mat, 1); 344 PetscAssertPointer(zerorows, 2); 345 PetscCall(MatFindNonzeroRows(mat, &keptrows)); 346 /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows. 347 In keeping with this convention, we set zerorows to NULL if there are no zero 348 rows. */ 349 if (keptrows == NULL) { 350 *zerorows = NULL; 351 } else { 352 PetscCall(MatGetOwnershipRange(mat, &m, &n)); 353 PetscCall(ISComplement(keptrows, m, n, zerorows)); 354 PetscCall(ISDestroy(&keptrows)); 355 } 356 PetscFunctionReturn(PETSC_SUCCESS); 357 } 358 359 /*@ 360 MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling 361 362 Not Collective 363 364 Input Parameter: 365 . A - the matrix 366 367 Output Parameter: 368 . a - the diagonal part (which is a SEQUENTIAL matrix) 369 370 Level: advanced 371 372 Notes: 373 See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix. 374 375 Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation. 376 377 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ` 378 @*/ 379 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) 380 { 381 PetscFunctionBegin; 382 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 383 PetscValidType(A, 1); 384 PetscAssertPointer(a, 2); 385 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 386 if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a); 387 else { 388 PetscMPIInt size; 389 390 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 391 PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name); 392 *a = A; 393 } 394 PetscFunctionReturn(PETSC_SUCCESS); 395 } 396 397 /*@ 398 MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries. 399 400 Collective 401 402 Input Parameter: 403 . mat - the matrix 404 405 Output Parameter: 406 . trace - the sum of the diagonal entries 407 408 Level: advanced 409 410 .seealso: [](ch_matrices), `Mat` 411 @*/ 412 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) 413 { 414 Vec diag; 415 416 PetscFunctionBegin; 417 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 418 PetscAssertPointer(trace, 2); 419 PetscCall(MatCreateVecs(mat, &diag, NULL)); 420 PetscCall(MatGetDiagonal(mat, diag)); 421 PetscCall(VecSum(diag, trace)); 422 PetscCall(VecDestroy(&diag)); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 MatRealPart - Zeros out the imaginary part of the matrix 428 429 Logically Collective 430 431 Input Parameter: 432 . mat - the matrix 433 434 Level: advanced 435 436 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()` 437 @*/ 438 PetscErrorCode MatRealPart(Mat mat) 439 { 440 PetscFunctionBegin; 441 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 442 PetscValidType(mat, 1); 443 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 444 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 445 MatCheckPreallocated(mat, 1); 446 PetscUseTypeMethod(mat, realpart); 447 PetscFunctionReturn(PETSC_SUCCESS); 448 } 449 450 /*@C 451 MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix 452 453 Collective 454 455 Input Parameter: 456 . mat - the matrix 457 458 Output Parameters: 459 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block) 460 - ghosts - the global indices of the ghost points 461 462 Level: advanced 463 464 Note: 465 `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()` 466 467 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()` 468 @*/ 469 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) 470 { 471 PetscFunctionBegin; 472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 473 PetscValidType(mat, 1); 474 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 475 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 476 if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts); 477 else { 478 if (nghosts) *nghosts = 0; 479 if (ghosts) *ghosts = NULL; 480 } 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part 486 487 Logically Collective 488 489 Input Parameter: 490 . mat - the matrix 491 492 Level: advanced 493 494 .seealso: [](ch_matrices), `Mat`, `MatRealPart()` 495 @*/ 496 PetscErrorCode MatImaginaryPart(Mat mat) 497 { 498 PetscFunctionBegin; 499 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 500 PetscValidType(mat, 1); 501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 503 MatCheckPreallocated(mat, 1); 504 PetscUseTypeMethod(mat, imaginarypart); 505 PetscFunctionReturn(PETSC_SUCCESS); 506 } 507 508 /*@ 509 MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure 510 511 Not Collective 512 513 Input Parameter: 514 . mat - the matrix 515 516 Output Parameters: 517 + missing - is any diagonal entry missing 518 - dd - first diagonal entry that is missing (optional) on this process 519 520 Level: advanced 521 522 Note: 523 This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value 524 525 .seealso: [](ch_matrices), `Mat` 526 @*/ 527 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) 528 { 529 PetscFunctionBegin; 530 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 531 PetscValidType(mat, 1); 532 PetscAssertPointer(missing, 2); 533 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name); 534 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 535 PetscUseTypeMethod(mat, missingdiagonal, missing, dd); 536 PetscFunctionReturn(PETSC_SUCCESS); 537 } 538 539 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 540 /*@C 541 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 542 for each row that you get to ensure that your application does 543 not bleed memory. 544 545 Not Collective 546 547 Input Parameters: 548 + mat - the matrix 549 - row - the row to get 550 551 Output Parameters: 552 + ncols - if not `NULL`, the number of nonzeros in `row` 553 . cols - if not `NULL`, the column numbers 554 - vals - if not `NULL`, the numerical values 555 556 Level: advanced 557 558 Notes: 559 This routine is provided for people who need to have direct access 560 to the structure of a matrix. We hope that we provide enough 561 high-level matrix routines that few users will need it. 562 563 `MatGetRow()` always returns 0-based column indices, regardless of 564 whether the internal representation is 0-based (default) or 1-based. 565 566 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 567 not wish to extract these quantities. 568 569 The user can only examine the values extracted with `MatGetRow()`; 570 the values CANNOT be altered. To change the matrix entries, one 571 must use `MatSetValues()`. 572 573 You can only have one call to `MatGetRow()` outstanding for a particular 574 matrix at a time, per processor. `MatGetRow()` can only obtain rows 575 associated with the given processor, it cannot get rows from the 576 other processors; for that we suggest using `MatCreateSubMatrices()`, then 577 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 578 is in the global number of rows. 579 580 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 581 582 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 583 584 Fortran Note: 585 .vb 586 PetscInt, pointer :: cols(:) 587 PetscScalar, pointer :: vals(:) 588 .ve 589 590 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 591 @*/ 592 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 593 { 594 PetscInt incols; 595 596 PetscFunctionBegin; 597 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 598 PetscValidType(mat, 1); 599 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 600 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 601 MatCheckPreallocated(mat, 1); 602 PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend); 603 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 604 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 605 if (ncols) *ncols = incols; 606 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 607 PetscFunctionReturn(PETSC_SUCCESS); 608 } 609 610 /*@ 611 MatConjugate - replaces the matrix values with their complex conjugates 612 613 Logically Collective 614 615 Input Parameter: 616 . mat - the matrix 617 618 Level: advanced 619 620 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 621 @*/ 622 PetscErrorCode MatConjugate(Mat mat) 623 { 624 PetscFunctionBegin; 625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 626 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 627 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 628 PetscUseTypeMethod(mat, conjugate); 629 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 630 } 631 PetscFunctionReturn(PETSC_SUCCESS); 632 } 633 634 /*@C 635 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 636 637 Not Collective 638 639 Input Parameters: 640 + mat - the matrix 641 . row - the row to get 642 . ncols - the number of nonzeros 643 . cols - the columns of the nonzeros 644 - vals - if nonzero the column values 645 646 Level: advanced 647 648 Notes: 649 This routine should be called after you have finished examining the entries. 650 651 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 652 us of the array after it has been restored. If you pass `NULL`, it will 653 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 654 655 Fortran Note: 656 .vb 657 PetscInt, pointer :: cols(:) 658 PetscScalar, pointer :: vals(:) 659 .ve 660 661 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 662 @*/ 663 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 664 { 665 PetscFunctionBegin; 666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 667 if (ncols) PetscAssertPointer(ncols, 3); 668 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 669 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 670 if (ncols) *ncols = 0; 671 if (cols) *cols = NULL; 672 if (vals) *vals = NULL; 673 PetscFunctionReturn(PETSC_SUCCESS); 674 } 675 676 /*@ 677 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 678 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 679 680 Not Collective 681 682 Input Parameter: 683 . mat - the matrix 684 685 Level: advanced 686 687 Note: 688 The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format. 689 690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 691 @*/ 692 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 693 { 694 PetscFunctionBegin; 695 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 696 PetscValidType(mat, 1); 697 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 698 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 699 MatCheckPreallocated(mat, 1); 700 PetscTryTypeMethod(mat, getrowuppertriangular); 701 PetscFunctionReturn(PETSC_SUCCESS); 702 } 703 704 /*@ 705 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 706 707 Not Collective 708 709 Input Parameter: 710 . mat - the matrix 711 712 Level: advanced 713 714 Note: 715 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 716 717 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 718 @*/ 719 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 720 { 721 PetscFunctionBegin; 722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 723 PetscValidType(mat, 1); 724 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 725 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 726 MatCheckPreallocated(mat, 1); 727 PetscTryTypeMethod(mat, restorerowuppertriangular); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefix - Sets the prefix used for searching for all 733 `Mat` options in the database. 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names 740 741 Level: advanced 742 743 Notes: 744 A hyphen (-) must NOT be given at the beginning of the prefix name. 745 The first character of all runtime options is AUTOMATICALLY the hyphen. 746 747 This is NOT used for options for the factorization of the matrix. Normally the 748 prefix is automatically passed in from the PC calling the factorization. To set 749 it directly use `MatSetOptionsPrefixFactor()` 750 751 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 752 @*/ 753 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 754 { 755 PetscFunctionBegin; 756 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 757 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 758 PetscFunctionReturn(PETSC_SUCCESS); 759 } 760 761 /*@ 762 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 763 for matrices created with `MatGetFactor()` 764 765 Logically Collective 766 767 Input Parameters: 768 + A - the matrix 769 - prefix - the prefix to prepend to all option names for the factored matrix 770 771 Level: developer 772 773 Notes: 774 A hyphen (-) must NOT be given at the beginning of the prefix name. 775 The first character of all runtime options is AUTOMATICALLY the hyphen. 776 777 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 778 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 779 780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 781 @*/ 782 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 783 { 784 PetscFunctionBegin; 785 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 786 if (prefix) { 787 PetscAssertPointer(prefix, 2); 788 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 789 if (prefix != A->factorprefix) { 790 PetscCall(PetscFree(A->factorprefix)); 791 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 792 } 793 } else PetscCall(PetscFree(A->factorprefix)); 794 PetscFunctionReturn(PETSC_SUCCESS); 795 } 796 797 /*@ 798 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 799 for matrices created with `MatGetFactor()` 800 801 Logically Collective 802 803 Input Parameters: 804 + A - the matrix 805 - prefix - the prefix to prepend to all option names for the factored matrix 806 807 Level: developer 808 809 Notes: 810 A hyphen (-) must NOT be given at the beginning of the prefix name. 811 The first character of all runtime options is AUTOMATICALLY the hyphen. 812 813 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 814 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 815 816 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 817 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 818 `MatSetOptionsPrefix()` 819 @*/ 820 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 821 { 822 size_t len1, len2, new_len; 823 824 PetscFunctionBegin; 825 PetscValidHeader(A, 1); 826 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 827 if (!A->factorprefix) { 828 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 829 PetscFunctionReturn(PETSC_SUCCESS); 830 } 831 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 832 833 PetscCall(PetscStrlen(A->factorprefix, &len1)); 834 PetscCall(PetscStrlen(prefix, &len2)); 835 new_len = len1 + len2 + 1; 836 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 837 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 838 PetscFunctionReturn(PETSC_SUCCESS); 839 } 840 841 /*@ 842 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 843 matrix options in the database. 844 845 Logically Collective 846 847 Input Parameters: 848 + A - the matrix 849 - prefix - the prefix to prepend to all option names 850 851 Level: advanced 852 853 Note: 854 A hyphen (-) must NOT be given at the beginning of the prefix name. 855 The first character of all runtime options is AUTOMATICALLY the hyphen. 856 857 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 858 @*/ 859 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 860 { 861 PetscFunctionBegin; 862 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 863 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 864 PetscFunctionReturn(PETSC_SUCCESS); 865 } 866 867 /*@ 868 MatGetOptionsPrefix - Gets the prefix used for searching for all 869 matrix options in the database. 870 871 Not Collective 872 873 Input Parameter: 874 . A - the matrix 875 876 Output Parameter: 877 . prefix - pointer to the prefix string used 878 879 Level: advanced 880 881 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 882 @*/ 883 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 884 { 885 PetscFunctionBegin; 886 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 887 PetscAssertPointer(prefix, 2); 888 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 889 PetscFunctionReturn(PETSC_SUCCESS); 890 } 891 892 /*@ 893 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 894 895 Not Collective 896 897 Input Parameter: 898 . A - the matrix 899 900 Output Parameter: 901 . state - the object state 902 903 Level: advanced 904 905 Note: 906 Object state is an integer which gets increased every time 907 the object is changed. By saving and later querying the object state 908 one can determine whether information about the object is still current. 909 910 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 911 912 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 913 @*/ 914 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 915 { 916 PetscFunctionBegin; 917 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 918 PetscAssertPointer(state, 2); 919 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 920 PetscFunctionReturn(PETSC_SUCCESS); 921 } 922 923 /*@ 924 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 925 926 Collective 927 928 Input Parameter: 929 . A - the matrix 930 931 Level: beginner 932 933 Notes: 934 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 935 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 936 makes all of the preallocation space available 937 938 Current values in the matrix are lost in this call 939 940 Currently only supported for `MATAIJ` matrices. 941 942 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 943 @*/ 944 PetscErrorCode MatResetPreallocation(Mat A) 945 { 946 PetscFunctionBegin; 947 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 948 PetscValidType(A, 1); 949 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 950 PetscFunctionReturn(PETSC_SUCCESS); 951 } 952 953 /*@ 954 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 955 956 Collective 957 958 Input Parameter: 959 . A - the matrix 960 961 Level: intermediate 962 963 Notes: 964 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 965 966 Currently only supported for `MATAIJ` matrices. 967 968 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 969 @*/ 970 PetscErrorCode MatResetHash(Mat A) 971 { 972 PetscFunctionBegin; 973 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 974 PetscValidType(A, 1); 975 PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset to hash state after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()"); 976 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 977 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 978 /* These flags are used to determine whether certain setups occur */ 979 A->was_assembled = PETSC_FALSE; 980 A->assembled = PETSC_FALSE; 981 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 982 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 983 PetscFunctionReturn(PETSC_SUCCESS); 984 } 985 986 /*@ 987 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 988 989 Collective 990 991 Input Parameter: 992 . A - the matrix 993 994 Level: advanced 995 996 Notes: 997 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 998 setting values in the matrix. 999 1000 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 1001 1002 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 1003 @*/ 1004 PetscErrorCode MatSetUp(Mat A) 1005 { 1006 PetscFunctionBegin; 1007 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1008 if (!((PetscObject)A)->type_name) { 1009 PetscMPIInt size; 1010 1011 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 1012 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 1013 } 1014 if (!A->preallocated) PetscTryTypeMethod(A, setup); 1015 PetscCall(PetscLayoutSetUp(A->rmap)); 1016 PetscCall(PetscLayoutSetUp(A->cmap)); 1017 A->preallocated = PETSC_TRUE; 1018 PetscFunctionReturn(PETSC_SUCCESS); 1019 } 1020 1021 #if defined(PETSC_HAVE_SAWS) 1022 #include <petscviewersaws.h> 1023 #endif 1024 1025 /* 1026 If threadsafety is on extraneous matrices may be printed 1027 1028 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1029 */ 1030 #if !defined(PETSC_HAVE_THREADSAFETY) 1031 static PetscInt insidematview = 0; 1032 #endif 1033 1034 /*@ 1035 MatViewFromOptions - View properties of the matrix based on options set in the options database 1036 1037 Collective 1038 1039 Input Parameters: 1040 + A - the matrix 1041 . obj - optional additional object that provides the options prefix to use 1042 - name - command line option 1043 1044 Options Database Key: 1045 . -mat_view [viewertype]:... - the viewer and its options 1046 1047 Level: intermediate 1048 1049 Note: 1050 .vb 1051 If no value is provided ascii:stdout is used 1052 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1053 for example ascii::ascii_info prints just the information about the object not all details 1054 unless :append is given filename opens in write mode, overwriting what was already there 1055 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1056 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1057 socket[:port] defaults to the standard output port 1058 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1059 .ve 1060 1061 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1062 @*/ 1063 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1064 { 1065 PetscFunctionBegin; 1066 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1067 #if !defined(PETSC_HAVE_THREADSAFETY) 1068 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1069 #endif 1070 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1071 PetscFunctionReturn(PETSC_SUCCESS); 1072 } 1073 1074 /*@ 1075 MatView - display information about a matrix in a variety ways 1076 1077 Collective on viewer 1078 1079 Input Parameters: 1080 + mat - the matrix 1081 - viewer - visualization context 1082 1083 Options Database Keys: 1084 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1085 . -mat_view ::ascii_info_detail - Prints more detailed info 1086 . -mat_view - Prints matrix in ASCII format 1087 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1088 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1089 . -display <name> - Sets display name (default is host) 1090 . -draw_pause <sec> - Sets number of seconds to pause after display 1091 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1092 . -viewer_socket_machine <machine> - - 1093 . -viewer_socket_port <port> - - 1094 . -mat_view binary - save matrix to file in binary format 1095 - -viewer_binary_filename <name> - - 1096 1097 Level: beginner 1098 1099 Notes: 1100 The available visualization contexts include 1101 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1102 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1103 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1104 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1105 1106 The user can open alternative visualization contexts with 1107 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1108 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1109 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1110 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1111 1112 The user can call `PetscViewerPushFormat()` to specify the output 1113 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1114 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1115 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1116 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1117 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1118 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1119 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1120 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1121 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1122 1123 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1124 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1125 1126 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1127 1128 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1129 viewer is used. 1130 1131 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1132 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1133 1134 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1135 and then use the following mouse functions. 1136 .vb 1137 left mouse: zoom in 1138 middle mouse: zoom out 1139 right mouse: continue with the simulation 1140 .ve 1141 1142 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1143 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1144 @*/ 1145 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1146 { 1147 PetscInt rows, cols, rbs, cbs; 1148 PetscBool isascii, isstring, issaws; 1149 PetscViewerFormat format; 1150 PetscMPIInt size; 1151 1152 PetscFunctionBegin; 1153 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1154 PetscValidType(mat, 1); 1155 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1156 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1157 1158 PetscCall(PetscViewerGetFormat(viewer, &format)); 1159 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1160 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1161 1162 #if !defined(PETSC_HAVE_THREADSAFETY) 1163 insidematview++; 1164 #endif 1165 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1166 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1167 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1168 PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail"); 1169 1170 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1171 if (isascii) { 1172 if (!mat->preallocated) { 1173 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1174 #if !defined(PETSC_HAVE_THREADSAFETY) 1175 insidematview--; 1176 #endif 1177 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1178 PetscFunctionReturn(PETSC_SUCCESS); 1179 } 1180 if (!mat->assembled) { 1181 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1182 #if !defined(PETSC_HAVE_THREADSAFETY) 1183 insidematview--; 1184 #endif 1185 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1186 PetscFunctionReturn(PETSC_SUCCESS); 1187 } 1188 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1189 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1190 MatNullSpace nullsp, transnullsp; 1191 1192 PetscCall(PetscViewerASCIIPushTab(viewer)); 1193 PetscCall(MatGetSize(mat, &rows, &cols)); 1194 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1195 if (rbs != 1 || cbs != 1) { 1196 if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "%s\n", rows, cols, rbs, cbs, mat->bsizes ? " variable blocks set" : "")); 1197 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1198 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1199 if (mat->factortype) { 1200 MatSolverType solver; 1201 PetscCall(MatFactorGetSolverType(mat, &solver)); 1202 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1203 } 1204 if (mat->ops->getinfo) { 1205 MatInfo info; 1206 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1207 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1208 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1209 } 1210 PetscCall(MatGetNullSpace(mat, &nullsp)); 1211 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1212 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1213 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1214 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1215 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1216 PetscCall(PetscViewerASCIIPushTab(viewer)); 1217 PetscCall(MatProductView(mat, viewer)); 1218 PetscCall(PetscViewerASCIIPopTab(viewer)); 1219 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1220 IS tmp; 1221 1222 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1223 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1224 PetscCall(PetscViewerASCIIPushTab(viewer)); 1225 PetscCall(ISView(tmp, viewer)); 1226 PetscCall(PetscViewerASCIIPopTab(viewer)); 1227 PetscCall(ISDestroy(&tmp)); 1228 } 1229 } 1230 } else if (issaws) { 1231 #if defined(PETSC_HAVE_SAWS) 1232 PetscMPIInt rank; 1233 1234 PetscCall(PetscObjectName((PetscObject)mat)); 1235 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1236 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1237 #endif 1238 } else if (isstring) { 1239 const char *type; 1240 PetscCall(MatGetType(mat, &type)); 1241 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1242 PetscTryTypeMethod(mat, view, viewer); 1243 } 1244 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1245 PetscCall(PetscViewerASCIIPushTab(viewer)); 1246 PetscUseTypeMethod(mat, viewnative, viewer); 1247 PetscCall(PetscViewerASCIIPopTab(viewer)); 1248 } else if (mat->ops->view) { 1249 PetscCall(PetscViewerASCIIPushTab(viewer)); 1250 PetscUseTypeMethod(mat, view, viewer); 1251 PetscCall(PetscViewerASCIIPopTab(viewer)); 1252 } 1253 if (isascii) { 1254 PetscCall(PetscViewerGetFormat(viewer, &format)); 1255 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1256 } 1257 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1258 #if !defined(PETSC_HAVE_THREADSAFETY) 1259 insidematview--; 1260 #endif 1261 PetscFunctionReturn(PETSC_SUCCESS); 1262 } 1263 1264 #if defined(PETSC_USE_DEBUG) 1265 #include <../src/sys/totalview/tv_data_display.h> 1266 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1267 { 1268 TV_add_row("Local rows", "int", &mat->rmap->n); 1269 TV_add_row("Local columns", "int", &mat->cmap->n); 1270 TV_add_row("Global rows", "int", &mat->rmap->N); 1271 TV_add_row("Global columns", "int", &mat->cmap->N); 1272 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1273 return TV_format_OK; 1274 } 1275 #endif 1276 1277 /*@ 1278 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1279 with `MatView()`. The matrix format is determined from the options database. 1280 Generates a parallel MPI matrix if the communicator has more than one 1281 processor. The default matrix type is `MATAIJ`. 1282 1283 Collective 1284 1285 Input Parameters: 1286 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1287 or some related function before a call to `MatLoad()` 1288 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1289 1290 Options Database Key: 1291 . -matload_block_size <bs> - set block size 1292 1293 Level: beginner 1294 1295 Notes: 1296 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1297 `Mat` before calling this routine if you wish to set it from the options database. 1298 1299 `MatLoad()` automatically loads into the options database any options 1300 given in the file filename.info where filename is the name of the file 1301 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1302 file will be ignored if you use the -viewer_binary_skip_info option. 1303 1304 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1305 sets the default matrix type AIJ and sets the local and global sizes. 1306 If type and/or size is already set, then the same are used. 1307 1308 In parallel, each processor can load a subset of rows (or the 1309 entire matrix). This routine is especially useful when a large 1310 matrix is stored on disk and only part of it is desired on each 1311 processor. For example, a parallel solver may access only some of 1312 the rows from each processor. The algorithm used here reads 1313 relatively small blocks of data rather than reading the entire 1314 matrix and then subsetting it. 1315 1316 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1317 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1318 or the sequence like 1319 .vb 1320 `PetscViewer` v; 1321 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1322 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1323 `PetscViewerSetFromOptions`(v); 1324 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1325 `PetscViewerFileSetName`(v,"datafile"); 1326 .ve 1327 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1328 .vb 1329 -viewer_type {binary, hdf5} 1330 .ve 1331 1332 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1333 and src/mat/tutorials/ex10.c with the second approach. 1334 1335 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1336 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1337 Multiple objects, both matrices and vectors, can be stored within the same file. 1338 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1339 1340 Most users should not need to know the details of the binary storage 1341 format, since `MatLoad()` and `MatView()` completely hide these details. 1342 But for anyone who is interested, the standard binary matrix storage 1343 format is 1344 1345 .vb 1346 PetscInt MAT_FILE_CLASSID 1347 PetscInt number of rows 1348 PetscInt number of columns 1349 PetscInt total number of nonzeros 1350 PetscInt *number nonzeros in each row 1351 PetscInt *column indices of all nonzeros (starting index is zero) 1352 PetscScalar *values of all nonzeros 1353 .ve 1354 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1355 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 1356 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1357 1358 PETSc automatically does the byte swapping for 1359 machines that store the bytes reversed. Thus if you write your own binary 1360 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1361 and `PetscBinaryWrite()` to see how this may be done. 1362 1363 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1364 Each processor's chunk is loaded independently by its owning MPI process. 1365 Multiple objects, both matrices and vectors, can be stored within the same file. 1366 They are looked up by their PetscObject name. 1367 1368 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1369 by default the same structure and naming of the AIJ arrays and column count 1370 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1371 .vb 1372 save example.mat A b -v7.3 1373 .ve 1374 can be directly read by this routine (see Reference 1 for details). 1375 1376 Depending on your MATLAB version, this format might be a default, 1377 otherwise you can set it as default in Preferences. 1378 1379 Unless -nocompression flag is used to save the file in MATLAB, 1380 PETSc must be configured with ZLIB package. 1381 1382 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1383 1384 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1385 1386 Corresponding `MatView()` is not yet implemented. 1387 1388 The loaded matrix is actually a transpose of the original one in MATLAB, 1389 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1390 With this format, matrix is automatically transposed by PETSc, 1391 unless the matrix is marked as SPD or symmetric 1392 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1393 1394 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1395 1396 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1397 @*/ 1398 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1399 { 1400 PetscBool flg; 1401 1402 PetscFunctionBegin; 1403 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1404 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1405 1406 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1407 1408 flg = PETSC_FALSE; 1409 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1410 if (flg) { 1411 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1412 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1413 } 1414 flg = PETSC_FALSE; 1415 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1416 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1417 1418 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1419 PetscUseTypeMethod(mat, load, viewer); 1420 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1421 PetscFunctionReturn(PETSC_SUCCESS); 1422 } 1423 1424 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1425 { 1426 Mat_Redundant *redund = *redundant; 1427 1428 PetscFunctionBegin; 1429 if (redund) { 1430 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1431 PetscCall(ISDestroy(&redund->isrow)); 1432 PetscCall(ISDestroy(&redund->iscol)); 1433 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1434 } else { 1435 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1436 PetscCall(PetscFree(redund->sbuf_j)); 1437 PetscCall(PetscFree(redund->sbuf_a)); 1438 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1439 PetscCall(PetscFree(redund->rbuf_j[i])); 1440 PetscCall(PetscFree(redund->rbuf_a[i])); 1441 } 1442 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1443 } 1444 1445 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1446 PetscCall(PetscFree(redund)); 1447 } 1448 PetscFunctionReturn(PETSC_SUCCESS); 1449 } 1450 1451 /*@ 1452 MatDestroy - Frees space taken by a matrix. 1453 1454 Collective 1455 1456 Input Parameter: 1457 . A - the matrix 1458 1459 Level: beginner 1460 1461 Developer Note: 1462 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1463 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1464 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1465 if changes are needed here. 1466 1467 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1468 @*/ 1469 PetscErrorCode MatDestroy(Mat *A) 1470 { 1471 PetscFunctionBegin; 1472 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1473 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1474 if (--((PetscObject)*A)->refct > 0) { 1475 *A = NULL; 1476 PetscFunctionReturn(PETSC_SUCCESS); 1477 } 1478 1479 /* if memory was published with SAWs then destroy it */ 1480 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1481 PetscTryTypeMethod(*A, destroy); 1482 1483 PetscCall(PetscFree((*A)->factorprefix)); 1484 PetscCall(PetscFree((*A)->defaultvectype)); 1485 PetscCall(PetscFree((*A)->defaultrandtype)); 1486 PetscCall(PetscFree((*A)->bsizes)); 1487 PetscCall(PetscFree((*A)->solvertype)); 1488 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1489 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1490 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1491 PetscCall(MatProductClear(*A)); 1492 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1493 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1494 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1495 PetscCall(MatDestroy(&(*A)->schur)); 1496 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1497 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1498 PetscCall(PetscHeaderDestroy(A)); 1499 PetscFunctionReturn(PETSC_SUCCESS); 1500 } 1501 1502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1503 /*@ 1504 MatSetValues - Inserts or adds a block of values into a matrix. 1505 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1506 MUST be called after all calls to `MatSetValues()` have been completed. 1507 1508 Not Collective 1509 1510 Input Parameters: 1511 + mat - the matrix 1512 . m - the number of rows 1513 . idxm - the global indices of the rows 1514 . n - the number of columns 1515 . idxn - the global indices of the columns 1516 . v - a logically two-dimensional array of values 1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1518 1519 Level: beginner 1520 1521 Notes: 1522 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1523 1524 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1525 options cannot be mixed without intervening calls to the assembly 1526 routines. 1527 1528 `MatSetValues()` uses 0-based row and column numbers in Fortran 1529 as well as in C. 1530 1531 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1532 simply ignored. This allows easily inserting element stiffness matrices 1533 with homogeneous Dirichlet boundary conditions that you don't want represented 1534 in the matrix. 1535 1536 Efficiency Alert: 1537 The routine `MatSetValuesBlocked()` may offer much better efficiency 1538 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1539 1540 Fortran Notes: 1541 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1542 .vb 1543 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1544 .ve 1545 1546 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1547 1548 Developer Note: 1549 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1550 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1551 1552 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1553 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1554 @*/ 1555 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1556 { 1557 PetscFunctionBeginHot; 1558 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1559 PetscValidType(mat, 1); 1560 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1561 PetscAssertPointer(idxm, 3); 1562 PetscAssertPointer(idxn, 5); 1563 MatCheckPreallocated(mat, 1); 1564 1565 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1566 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1567 1568 if (PetscDefined(USE_DEBUG)) { 1569 PetscInt i, j; 1570 1571 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1572 if (v) { 1573 for (i = 0; i < m; i++) { 1574 for (j = 0; j < n; j++) { 1575 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1576 #if defined(PETSC_USE_COMPLEX) 1577 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]); 1578 #else 1579 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]); 1580 #endif 1581 } 1582 } 1583 } 1584 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); 1585 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); 1586 } 1587 1588 if (mat->assembled) { 1589 mat->was_assembled = PETSC_TRUE; 1590 mat->assembled = PETSC_FALSE; 1591 } 1592 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1593 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1594 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1595 PetscFunctionReturn(PETSC_SUCCESS); 1596 } 1597 1598 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1599 /*@ 1600 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1601 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1602 MUST be called after all calls to `MatSetValues()` have been completed. 1603 1604 Not Collective 1605 1606 Input Parameters: 1607 + mat - the matrix 1608 . ism - the rows to provide 1609 . isn - the columns to provide 1610 . v - a logically two-dimensional array of values 1611 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1612 1613 Level: beginner 1614 1615 Notes: 1616 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1617 1618 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1619 options cannot be mixed without intervening calls to the assembly 1620 routines. 1621 1622 `MatSetValues()` uses 0-based row and column numbers in Fortran 1623 as well as in C. 1624 1625 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1626 simply ignored. This allows easily inserting element stiffness matrices 1627 with homogeneous Dirichlet boundary conditions that you don't want represented 1628 in the matrix. 1629 1630 Efficiency Alert: 1631 The routine `MatSetValuesBlocked()` may offer much better efficiency 1632 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1633 1634 This is currently not optimized for any particular `ISType` 1635 1636 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1637 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1638 @*/ 1639 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1640 { 1641 PetscInt m, n; 1642 const PetscInt *rows, *cols; 1643 1644 PetscFunctionBeginHot; 1645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1646 PetscCall(ISGetIndices(ism, &rows)); 1647 PetscCall(ISGetIndices(isn, &cols)); 1648 PetscCall(ISGetLocalSize(ism, &m)); 1649 PetscCall(ISGetLocalSize(isn, &n)); 1650 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1651 PetscCall(ISRestoreIndices(ism, &rows)); 1652 PetscCall(ISRestoreIndices(isn, &cols)); 1653 PetscFunctionReturn(PETSC_SUCCESS); 1654 } 1655 1656 /*@ 1657 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1658 values into a matrix 1659 1660 Not Collective 1661 1662 Input Parameters: 1663 + mat - the matrix 1664 . row - the (block) row to set 1665 - v - a logically two-dimensional array of values 1666 1667 Level: intermediate 1668 1669 Notes: 1670 The values, `v`, are column-oriented (for the block version) and sorted 1671 1672 All the nonzero values in `row` must be provided 1673 1674 The matrix must have previously had its column indices set, likely by having been assembled. 1675 1676 `row` must belong to this MPI process 1677 1678 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1679 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1680 @*/ 1681 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1682 { 1683 PetscInt globalrow; 1684 1685 PetscFunctionBegin; 1686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1687 PetscValidType(mat, 1); 1688 PetscAssertPointer(v, 3); 1689 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1690 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1691 PetscFunctionReturn(PETSC_SUCCESS); 1692 } 1693 1694 /*@ 1695 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1696 values into a matrix 1697 1698 Not Collective 1699 1700 Input Parameters: 1701 + mat - the matrix 1702 . row - the (block) row to set 1703 - 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 1704 1705 Level: advanced 1706 1707 Notes: 1708 The values, `v`, are column-oriented for the block version. 1709 1710 All the nonzeros in `row` must be provided 1711 1712 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1713 1714 `row` must belong to this process 1715 1716 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1717 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1718 @*/ 1719 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1720 { 1721 PetscFunctionBeginHot; 1722 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1723 PetscValidType(mat, 1); 1724 MatCheckPreallocated(mat, 1); 1725 PetscAssertPointer(v, 3); 1726 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1727 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1728 mat->insertmode = INSERT_VALUES; 1729 1730 if (mat->assembled) { 1731 mat->was_assembled = PETSC_TRUE; 1732 mat->assembled = PETSC_FALSE; 1733 } 1734 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1735 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1736 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1737 PetscFunctionReturn(PETSC_SUCCESS); 1738 } 1739 1740 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1741 /*@ 1742 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1743 Using structured grid indexing 1744 1745 Not Collective 1746 1747 Input Parameters: 1748 + mat - the matrix 1749 . m - number of rows being entered 1750 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1751 . n - number of columns being entered 1752 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1753 . v - a logically two-dimensional array of values 1754 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1755 1756 Level: beginner 1757 1758 Notes: 1759 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1760 1761 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1762 options cannot be mixed without intervening calls to the assembly 1763 routines. 1764 1765 The grid coordinates are across the entire grid, not just the local portion 1766 1767 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1768 as well as in C. 1769 1770 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1771 1772 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1773 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1774 1775 The columns and rows in the stencil passed in MUST be contained within the 1776 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1777 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1778 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1779 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1780 1781 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1782 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1783 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1784 `DM_BOUNDARY_PERIODIC` boundary type. 1785 1786 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 1787 a single value per point) you can skip filling those indices. 1788 1789 Inspired by the structured grid interface to the HYPRE package 1790 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1791 1792 Efficiency Alert: 1793 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1794 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1795 1796 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1797 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1798 @*/ 1799 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1800 { 1801 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1802 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1803 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1804 1805 PetscFunctionBegin; 1806 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1807 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1808 PetscValidType(mat, 1); 1809 PetscAssertPointer(idxm, 3); 1810 PetscAssertPointer(idxn, 5); 1811 1812 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1813 jdxm = buf; 1814 jdxn = buf + m; 1815 } else { 1816 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1817 jdxm = bufm; 1818 jdxn = bufn; 1819 } 1820 for (i = 0; i < m; i++) { 1821 for (j = 0; j < 3 - sdim; j++) dxm++; 1822 tmp = *dxm++ - starts[0]; 1823 for (j = 0; j < dim - 1; j++) { 1824 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1825 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1826 } 1827 if (mat->stencil.noc) dxm++; 1828 jdxm[i] = tmp; 1829 } 1830 for (i = 0; i < n; i++) { 1831 for (j = 0; j < 3 - sdim; j++) dxn++; 1832 tmp = *dxn++ - starts[0]; 1833 for (j = 0; j < dim - 1; j++) { 1834 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1835 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1836 } 1837 if (mat->stencil.noc) dxn++; 1838 jdxn[i] = tmp; 1839 } 1840 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1841 PetscCall(PetscFree2(bufm, bufn)); 1842 PetscFunctionReturn(PETSC_SUCCESS); 1843 } 1844 1845 /*@ 1846 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1847 Using structured grid indexing 1848 1849 Not Collective 1850 1851 Input Parameters: 1852 + mat - the matrix 1853 . m - number of rows being entered 1854 . idxm - grid coordinates for matrix rows being entered 1855 . n - number of columns being entered 1856 . idxn - grid coordinates for matrix columns being entered 1857 . v - a logically two-dimensional array of values 1858 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1859 1860 Level: beginner 1861 1862 Notes: 1863 By default the values, `v`, are row-oriented and unsorted. 1864 See `MatSetOption()` for other options. 1865 1866 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1867 options cannot be mixed without intervening calls to the assembly 1868 routines. 1869 1870 The grid coordinates are across the entire grid, not just the local portion 1871 1872 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1873 as well as in C. 1874 1875 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1876 1877 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1878 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1879 1880 The columns and rows in the stencil passed in MUST be contained within the 1881 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1882 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1883 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1884 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1885 1886 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1887 simply ignored. This allows easily inserting element stiffness matrices 1888 with homogeneous Dirichlet boundary conditions that you don't want represented 1889 in the matrix. 1890 1891 Inspired by the structured grid interface to the HYPRE package 1892 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1893 1894 Fortran Note: 1895 `idxm` and `idxn` should be declared as 1896 .vb 1897 MatStencil idxm(4,m),idxn(4,n) 1898 .ve 1899 and the values inserted using 1900 .vb 1901 idxm(MatStencil_i,1) = i 1902 idxm(MatStencil_j,1) = j 1903 idxm(MatStencil_k,1) = k 1904 etc 1905 .ve 1906 1907 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1908 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1909 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1910 @*/ 1911 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1912 { 1913 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1914 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1915 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1916 1917 PetscFunctionBegin; 1918 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1920 PetscValidType(mat, 1); 1921 PetscAssertPointer(idxm, 3); 1922 PetscAssertPointer(idxn, 5); 1923 PetscAssertPointer(v, 6); 1924 1925 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1926 jdxm = buf; 1927 jdxn = buf + m; 1928 } else { 1929 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1930 jdxm = bufm; 1931 jdxn = bufn; 1932 } 1933 for (i = 0; i < m; i++) { 1934 for (j = 0; j < 3 - sdim; j++) dxm++; 1935 tmp = *dxm++ - starts[0]; 1936 for (j = 0; j < sdim - 1; j++) { 1937 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1938 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1939 } 1940 dxm++; 1941 jdxm[i] = tmp; 1942 } 1943 for (i = 0; i < n; i++) { 1944 for (j = 0; j < 3 - sdim; j++) dxn++; 1945 tmp = *dxn++ - starts[0]; 1946 for (j = 0; j < sdim - 1; j++) { 1947 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1948 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1949 } 1950 dxn++; 1951 jdxn[i] = tmp; 1952 } 1953 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1954 PetscCall(PetscFree2(bufm, bufn)); 1955 PetscFunctionReturn(PETSC_SUCCESS); 1956 } 1957 1958 /*@ 1959 MatSetStencil - Sets the grid information for setting values into a matrix via 1960 `MatSetValuesStencil()` 1961 1962 Not Collective 1963 1964 Input Parameters: 1965 + mat - the matrix 1966 . dim - dimension of the grid 1, 2, or 3 1967 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1968 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1969 - dof - number of degrees of freedom per node 1970 1971 Level: beginner 1972 1973 Notes: 1974 Inspired by the structured grid interface to the HYPRE package 1975 (www.llnl.gov/CASC/hyper) 1976 1977 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1978 user. 1979 1980 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1981 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1982 @*/ 1983 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1984 { 1985 PetscFunctionBegin; 1986 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1987 PetscAssertPointer(dims, 3); 1988 PetscAssertPointer(starts, 4); 1989 1990 mat->stencil.dim = dim + (dof > 1); 1991 for (PetscInt i = 0; i < dim; i++) { 1992 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1993 mat->stencil.starts[i] = starts[dim - i - 1]; 1994 } 1995 mat->stencil.dims[dim] = dof; 1996 mat->stencil.starts[dim] = 0; 1997 mat->stencil.noc = (PetscBool)(dof == 1); 1998 PetscFunctionReturn(PETSC_SUCCESS); 1999 } 2000 2001 /*@ 2002 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2003 2004 Not Collective 2005 2006 Input Parameters: 2007 + mat - the matrix 2008 . m - the number of block rows 2009 . idxm - the global block indices 2010 . n - the number of block columns 2011 . idxn - the global block indices 2012 . v - a logically two-dimensional array of values 2013 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2014 2015 Level: intermediate 2016 2017 Notes: 2018 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2019 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2020 2021 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2022 NOT the total number of rows/columns; for example, if the block size is 2 and 2023 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2024 The values in `idxm` would be 1 2; that is the first index for each block divided by 2025 the block size. 2026 2027 You must call `MatSetBlockSize()` when constructing this matrix (before 2028 preallocating it). 2029 2030 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2031 2032 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2033 options cannot be mixed without intervening calls to the assembly 2034 routines. 2035 2036 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2037 as well as in C. 2038 2039 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2040 simply ignored. This allows easily inserting element stiffness matrices 2041 with homogeneous Dirichlet boundary conditions that you don't want represented 2042 in the matrix. 2043 2044 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2045 internal searching must be done to determine where to place the 2046 data in the matrix storage space. By instead inserting blocks of 2047 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2048 reduced. 2049 2050 Example: 2051 .vb 2052 Suppose m=n=2 and block size(bs) = 2 The array is 2053 2054 1 2 | 3 4 2055 5 6 | 7 8 2056 - - - | - - - 2057 9 10 | 11 12 2058 13 14 | 15 16 2059 2060 v[] should be passed in like 2061 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2062 2063 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2064 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2065 .ve 2066 2067 Fortran Notes: 2068 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2069 .vb 2070 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2071 .ve 2072 2073 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2074 2075 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2076 @*/ 2077 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2078 { 2079 PetscFunctionBeginHot; 2080 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2081 PetscValidType(mat, 1); 2082 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2083 PetscAssertPointer(idxm, 3); 2084 PetscAssertPointer(idxn, 5); 2085 MatCheckPreallocated(mat, 1); 2086 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2087 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2088 if (PetscDefined(USE_DEBUG)) { 2089 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2090 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2091 } 2092 if (PetscDefined(USE_DEBUG)) { 2093 PetscInt rbs, cbs, M, N, i; 2094 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2095 PetscCall(MatGetSize(mat, &M, &N)); 2096 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); 2097 for (i = 0; i < n; i++) 2098 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); 2099 } 2100 if (mat->assembled) { 2101 mat->was_assembled = PETSC_TRUE; 2102 mat->assembled = PETSC_FALSE; 2103 } 2104 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2105 if (mat->ops->setvaluesblocked) { 2106 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2107 } else { 2108 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2109 PetscInt i, j, bs, cbs; 2110 2111 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2112 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2113 iidxm = buf; 2114 iidxn = buf + m * bs; 2115 } else { 2116 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2117 iidxm = bufr; 2118 iidxn = bufc; 2119 } 2120 for (i = 0; i < m; i++) { 2121 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2122 } 2123 if (m != n || bs != cbs || idxm != idxn) { 2124 for (i = 0; i < n; i++) { 2125 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2126 } 2127 } else iidxn = iidxm; 2128 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2129 PetscCall(PetscFree2(bufr, bufc)); 2130 } 2131 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2132 PetscFunctionReturn(PETSC_SUCCESS); 2133 } 2134 2135 /*@ 2136 MatGetValues - Gets a block of local values from a matrix. 2137 2138 Not Collective; can only return values that are owned by the give process 2139 2140 Input Parameters: 2141 + mat - the matrix 2142 . v - a logically two-dimensional array for storing the values 2143 . m - the number of rows 2144 . idxm - the global indices of the rows 2145 . n - the number of columns 2146 - idxn - the global indices of the columns 2147 2148 Level: advanced 2149 2150 Notes: 2151 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2152 The values, `v`, are then returned in a row-oriented format, 2153 analogous to that used by default in `MatSetValues()`. 2154 2155 `MatGetValues()` uses 0-based row and column numbers in 2156 Fortran as well as in C. 2157 2158 `MatGetValues()` requires that the matrix has been assembled 2159 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2160 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2161 without intermediate matrix assembly. 2162 2163 Negative row or column indices will be ignored and those locations in `v` will be 2164 left unchanged. 2165 2166 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2167 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2168 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2169 2170 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2171 @*/ 2172 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2173 { 2174 PetscFunctionBegin; 2175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2176 PetscValidType(mat, 1); 2177 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2178 PetscAssertPointer(idxm, 3); 2179 PetscAssertPointer(idxn, 5); 2180 PetscAssertPointer(v, 6); 2181 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2182 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2183 MatCheckPreallocated(mat, 1); 2184 2185 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2186 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2187 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2188 PetscFunctionReturn(PETSC_SUCCESS); 2189 } 2190 2191 /*@ 2192 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2193 defined previously by `MatSetLocalToGlobalMapping()` 2194 2195 Not Collective 2196 2197 Input Parameters: 2198 + mat - the matrix 2199 . nrow - number of rows 2200 . irow - the row local indices 2201 . ncol - number of columns 2202 - icol - the column local indices 2203 2204 Output Parameter: 2205 . y - a logically two-dimensional array of values 2206 2207 Level: advanced 2208 2209 Notes: 2210 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2211 2212 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, 2213 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2214 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2215 with `MatSetLocalToGlobalMapping()`. 2216 2217 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2218 `MatSetValuesLocal()`, `MatGetValues()` 2219 @*/ 2220 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2221 { 2222 PetscFunctionBeginHot; 2223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2224 PetscValidType(mat, 1); 2225 MatCheckPreallocated(mat, 1); 2226 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2227 PetscAssertPointer(irow, 3); 2228 PetscAssertPointer(icol, 5); 2229 if (PetscDefined(USE_DEBUG)) { 2230 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2231 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2232 } 2233 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2234 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2235 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2236 else { 2237 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2238 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2239 irowm = buf; 2240 icolm = buf + nrow; 2241 } else { 2242 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2243 irowm = bufr; 2244 icolm = bufc; 2245 } 2246 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2247 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2248 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2249 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2250 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2251 PetscCall(PetscFree2(bufr, bufc)); 2252 } 2253 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2254 PetscFunctionReturn(PETSC_SUCCESS); 2255 } 2256 2257 /*@ 2258 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2259 the same size. Currently, this can only be called once and creates the given matrix. 2260 2261 Not Collective 2262 2263 Input Parameters: 2264 + mat - the matrix 2265 . nb - the number of blocks 2266 . bs - the number of rows (and columns) in each block 2267 . rows - a concatenation of the rows for each block 2268 - v - a concatenation of logically two-dimensional arrays of values 2269 2270 Level: advanced 2271 2272 Notes: 2273 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2274 2275 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2276 2277 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2278 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2279 @*/ 2280 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2281 { 2282 PetscFunctionBegin; 2283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2284 PetscValidType(mat, 1); 2285 PetscAssertPointer(rows, 4); 2286 PetscAssertPointer(v, 5); 2287 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2288 2289 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2290 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2291 else { 2292 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2293 } 2294 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2295 PetscFunctionReturn(PETSC_SUCCESS); 2296 } 2297 2298 /*@ 2299 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2300 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2301 using a local (per-processor) numbering. 2302 2303 Not Collective 2304 2305 Input Parameters: 2306 + x - the matrix 2307 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2308 - cmapping - column mapping 2309 2310 Level: intermediate 2311 2312 Note: 2313 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2314 2315 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2316 @*/ 2317 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2318 { 2319 PetscFunctionBegin; 2320 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2321 PetscValidType(x, 1); 2322 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2323 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2324 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2325 else { 2326 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2327 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2328 } 2329 PetscFunctionReturn(PETSC_SUCCESS); 2330 } 2331 2332 /*@ 2333 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2334 2335 Not Collective 2336 2337 Input Parameter: 2338 . A - the matrix 2339 2340 Output Parameters: 2341 + rmapping - row mapping 2342 - cmapping - column mapping 2343 2344 Level: advanced 2345 2346 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2347 @*/ 2348 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2349 { 2350 PetscFunctionBegin; 2351 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2352 PetscValidType(A, 1); 2353 if (rmapping) { 2354 PetscAssertPointer(rmapping, 2); 2355 *rmapping = A->rmap->mapping; 2356 } 2357 if (cmapping) { 2358 PetscAssertPointer(cmapping, 3); 2359 *cmapping = A->cmap->mapping; 2360 } 2361 PetscFunctionReturn(PETSC_SUCCESS); 2362 } 2363 2364 /*@ 2365 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2366 2367 Logically Collective 2368 2369 Input Parameters: 2370 + A - the matrix 2371 . rmap - row layout 2372 - cmap - column layout 2373 2374 Level: advanced 2375 2376 Note: 2377 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2378 2379 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2380 @*/ 2381 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2382 { 2383 PetscFunctionBegin; 2384 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2385 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2386 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2387 PetscFunctionReturn(PETSC_SUCCESS); 2388 } 2389 2390 /*@ 2391 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2392 2393 Not Collective 2394 2395 Input Parameter: 2396 . A - the matrix 2397 2398 Output Parameters: 2399 + rmap - row layout 2400 - cmap - column layout 2401 2402 Level: advanced 2403 2404 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2405 @*/ 2406 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2407 { 2408 PetscFunctionBegin; 2409 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2410 PetscValidType(A, 1); 2411 if (rmap) { 2412 PetscAssertPointer(rmap, 2); 2413 *rmap = A->rmap; 2414 } 2415 if (cmap) { 2416 PetscAssertPointer(cmap, 3); 2417 *cmap = A->cmap; 2418 } 2419 PetscFunctionReturn(PETSC_SUCCESS); 2420 } 2421 2422 /*@ 2423 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2424 using a local numbering of the rows and columns. 2425 2426 Not Collective 2427 2428 Input Parameters: 2429 + mat - the matrix 2430 . nrow - number of rows 2431 . irow - the row local indices 2432 . ncol - number of columns 2433 . icol - the column local indices 2434 . y - a logically two-dimensional array of values 2435 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2436 2437 Level: intermediate 2438 2439 Notes: 2440 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2441 2442 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2443 options cannot be mixed without intervening calls to the assembly 2444 routines. 2445 2446 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2447 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2448 2449 Fortran Notes: 2450 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2451 .vb 2452 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2453 .ve 2454 2455 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2456 2457 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2458 `MatGetValuesLocal()` 2459 @*/ 2460 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2461 { 2462 PetscFunctionBeginHot; 2463 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2464 PetscValidType(mat, 1); 2465 MatCheckPreallocated(mat, 1); 2466 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2467 PetscAssertPointer(irow, 3); 2468 PetscAssertPointer(icol, 5); 2469 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2470 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2471 if (PetscDefined(USE_DEBUG)) { 2472 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2473 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2474 } 2475 2476 if (mat->assembled) { 2477 mat->was_assembled = PETSC_TRUE; 2478 mat->assembled = PETSC_FALSE; 2479 } 2480 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2481 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2482 else { 2483 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2484 const PetscInt *irowm, *icolm; 2485 2486 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2487 bufr = buf; 2488 bufc = buf + nrow; 2489 irowm = bufr; 2490 icolm = bufc; 2491 } else { 2492 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2493 irowm = bufr; 2494 icolm = bufc; 2495 } 2496 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2497 else irowm = irow; 2498 if (mat->cmap->mapping) { 2499 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2500 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2501 } else icolm = irowm; 2502 } else icolm = icol; 2503 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2504 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2505 } 2506 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2507 PetscFunctionReturn(PETSC_SUCCESS); 2508 } 2509 2510 /*@ 2511 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2512 using a local ordering of the nodes a block at a time. 2513 2514 Not Collective 2515 2516 Input Parameters: 2517 + mat - the matrix 2518 . nrow - number of rows 2519 . irow - the row local indices 2520 . ncol - number of columns 2521 . icol - the column local indices 2522 . y - a logically two-dimensional array of values 2523 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2524 2525 Level: intermediate 2526 2527 Notes: 2528 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2529 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2530 2531 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2532 options cannot be mixed without intervening calls to the assembly 2533 routines. 2534 2535 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2536 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2537 2538 Fortran Notes: 2539 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2540 .vb 2541 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2542 .ve 2543 2544 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2545 2546 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2547 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2548 @*/ 2549 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2550 { 2551 PetscFunctionBeginHot; 2552 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2553 PetscValidType(mat, 1); 2554 MatCheckPreallocated(mat, 1); 2555 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2556 PetscAssertPointer(irow, 3); 2557 PetscAssertPointer(icol, 5); 2558 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2559 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2560 if (PetscDefined(USE_DEBUG)) { 2561 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2562 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); 2563 } 2564 2565 if (mat->assembled) { 2566 mat->was_assembled = PETSC_TRUE; 2567 mat->assembled = PETSC_FALSE; 2568 } 2569 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2570 PetscInt irbs, rbs; 2571 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2572 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2573 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2574 } 2575 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2576 PetscInt icbs, cbs; 2577 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2578 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2579 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2580 } 2581 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2582 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2583 else { 2584 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2585 const PetscInt *irowm, *icolm; 2586 2587 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2588 bufr = buf; 2589 bufc = buf + nrow; 2590 irowm = bufr; 2591 icolm = bufc; 2592 } else { 2593 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2594 irowm = bufr; 2595 icolm = bufc; 2596 } 2597 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2598 else irowm = irow; 2599 if (mat->cmap->mapping) { 2600 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2601 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2602 } else icolm = irowm; 2603 } else icolm = icol; 2604 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2605 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2606 } 2607 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2608 PetscFunctionReturn(PETSC_SUCCESS); 2609 } 2610 2611 /*@ 2612 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2613 2614 Collective 2615 2616 Input Parameters: 2617 + mat - the matrix 2618 - x - the vector to be multiplied 2619 2620 Output Parameter: 2621 . y - the result 2622 2623 Level: developer 2624 2625 Note: 2626 The vectors `x` and `y` cannot be the same. I.e., one cannot 2627 call `MatMultDiagonalBlock`(A,y,y). 2628 2629 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2630 @*/ 2631 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2632 { 2633 PetscFunctionBegin; 2634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2635 PetscValidType(mat, 1); 2636 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2637 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2638 2639 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2640 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2641 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2642 MatCheckPreallocated(mat, 1); 2643 2644 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2645 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2646 PetscFunctionReturn(PETSC_SUCCESS); 2647 } 2648 2649 /*@ 2650 MatMult - Computes the matrix-vector product, $y = Ax$. 2651 2652 Neighbor-wise Collective 2653 2654 Input Parameters: 2655 + mat - the matrix 2656 - x - the vector to be multiplied 2657 2658 Output Parameter: 2659 . y - the result 2660 2661 Level: beginner 2662 2663 Note: 2664 The vectors `x` and `y` cannot be the same. I.e., one cannot 2665 call `MatMult`(A,y,y). 2666 2667 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2668 @*/ 2669 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2670 { 2671 PetscFunctionBegin; 2672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2673 PetscValidType(mat, 1); 2674 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2675 VecCheckAssembled(x); 2676 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2677 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2678 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2679 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2680 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); 2681 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); 2682 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); 2683 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); 2684 PetscCall(VecSetErrorIfLocked(y, 3)); 2685 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2686 MatCheckPreallocated(mat, 1); 2687 2688 PetscCall(VecLockReadPush(x)); 2689 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2690 PetscUseTypeMethod(mat, mult, x, y); 2691 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2692 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2693 PetscCall(VecLockReadPop(x)); 2694 PetscFunctionReturn(PETSC_SUCCESS); 2695 } 2696 2697 /*@ 2698 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2699 2700 Neighbor-wise Collective 2701 2702 Input Parameters: 2703 + mat - the matrix 2704 - x - the vector to be multiplied 2705 2706 Output Parameter: 2707 . y - the result 2708 2709 Level: beginner 2710 2711 Notes: 2712 The vectors `x` and `y` cannot be the same. I.e., one cannot 2713 call `MatMultTranspose`(A,y,y). 2714 2715 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2716 use `MatMultHermitianTranspose()` 2717 2718 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2719 @*/ 2720 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2721 { 2722 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2723 2724 PetscFunctionBegin; 2725 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2726 PetscValidType(mat, 1); 2727 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2728 VecCheckAssembled(x); 2729 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2730 2731 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2733 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2734 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); 2735 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); 2736 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); 2737 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); 2738 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2739 MatCheckPreallocated(mat, 1); 2740 2741 if (!mat->ops->multtranspose) { 2742 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2743 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); 2744 } else op = mat->ops->multtranspose; 2745 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2746 PetscCall(VecLockReadPush(x)); 2747 PetscCall((*op)(mat, x, y)); 2748 PetscCall(VecLockReadPop(x)); 2749 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2750 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2751 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2752 PetscFunctionReturn(PETSC_SUCCESS); 2753 } 2754 2755 /*@ 2756 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2757 2758 Neighbor-wise Collective 2759 2760 Input Parameters: 2761 + mat - the matrix 2762 - x - the vector to be multiplied 2763 2764 Output Parameter: 2765 . y - the result 2766 2767 Level: beginner 2768 2769 Notes: 2770 The vectors `x` and `y` cannot be the same. I.e., one cannot 2771 call `MatMultHermitianTranspose`(A,y,y). 2772 2773 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2774 2775 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2776 2777 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2778 @*/ 2779 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2780 { 2781 PetscFunctionBegin; 2782 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2783 PetscValidType(mat, 1); 2784 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2785 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2786 2787 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2788 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2789 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2790 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); 2791 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); 2792 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); 2793 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); 2794 MatCheckPreallocated(mat, 1); 2795 2796 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2797 #if defined(PETSC_USE_COMPLEX) 2798 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2799 PetscCall(VecLockReadPush(x)); 2800 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2801 else PetscUseTypeMethod(mat, mult, x, y); 2802 PetscCall(VecLockReadPop(x)); 2803 } else { 2804 Vec w; 2805 PetscCall(VecDuplicate(x, &w)); 2806 PetscCall(VecCopy(x, w)); 2807 PetscCall(VecConjugate(w)); 2808 PetscCall(MatMultTranspose(mat, w, y)); 2809 PetscCall(VecDestroy(&w)); 2810 PetscCall(VecConjugate(y)); 2811 } 2812 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2813 #else 2814 PetscCall(MatMultTranspose(mat, x, y)); 2815 #endif 2816 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2817 PetscFunctionReturn(PETSC_SUCCESS); 2818 } 2819 2820 /*@ 2821 MatMultAdd - Computes $v3 = v2 + A * v1$. 2822 2823 Neighbor-wise Collective 2824 2825 Input Parameters: 2826 + mat - the matrix 2827 . v1 - the vector to be multiplied by `mat` 2828 - v2 - the vector to be added to the result 2829 2830 Output Parameter: 2831 . v3 - the result 2832 2833 Level: beginner 2834 2835 Note: 2836 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2837 call `MatMultAdd`(A,v1,v2,v1). 2838 2839 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2840 @*/ 2841 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2842 { 2843 PetscFunctionBegin; 2844 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2845 PetscValidType(mat, 1); 2846 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2847 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2848 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2849 2850 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2851 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2852 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); 2853 /* 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); 2854 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); */ 2855 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); 2856 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); 2857 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2858 MatCheckPreallocated(mat, 1); 2859 2860 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2861 PetscCall(VecLockReadPush(v1)); 2862 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2863 PetscCall(VecLockReadPop(v1)); 2864 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2865 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2866 PetscFunctionReturn(PETSC_SUCCESS); 2867 } 2868 2869 /*@ 2870 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2871 2872 Neighbor-wise Collective 2873 2874 Input Parameters: 2875 + mat - the matrix 2876 . v1 - the vector to be multiplied by the transpose of the matrix 2877 - v2 - the vector to be added to the result 2878 2879 Output Parameter: 2880 . v3 - the result 2881 2882 Level: beginner 2883 2884 Note: 2885 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2886 call `MatMultTransposeAdd`(A,v1,v2,v1). 2887 2888 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2889 @*/ 2890 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2891 { 2892 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2893 2894 PetscFunctionBegin; 2895 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2896 PetscValidType(mat, 1); 2897 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2898 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2899 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2900 2901 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2902 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2903 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); 2904 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); 2905 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); 2906 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2907 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2908 MatCheckPreallocated(mat, 1); 2909 2910 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2911 PetscCall(VecLockReadPush(v1)); 2912 PetscCall((*op)(mat, v1, v2, v3)); 2913 PetscCall(VecLockReadPop(v1)); 2914 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2915 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2916 PetscFunctionReturn(PETSC_SUCCESS); 2917 } 2918 2919 /*@ 2920 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2921 2922 Neighbor-wise Collective 2923 2924 Input Parameters: 2925 + mat - the matrix 2926 . v1 - the vector to be multiplied by the Hermitian transpose 2927 - v2 - the vector to be added to the result 2928 2929 Output Parameter: 2930 . v3 - the result 2931 2932 Level: beginner 2933 2934 Note: 2935 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2936 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2937 2938 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2939 @*/ 2940 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2941 { 2942 PetscFunctionBegin; 2943 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2944 PetscValidType(mat, 1); 2945 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2946 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2947 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2948 2949 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2950 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2951 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2952 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); 2953 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); 2954 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); 2955 MatCheckPreallocated(mat, 1); 2956 2957 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2958 PetscCall(VecLockReadPush(v1)); 2959 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2960 else { 2961 Vec w, z; 2962 PetscCall(VecDuplicate(v1, &w)); 2963 PetscCall(VecCopy(v1, w)); 2964 PetscCall(VecConjugate(w)); 2965 PetscCall(VecDuplicate(v3, &z)); 2966 PetscCall(MatMultTranspose(mat, w, z)); 2967 PetscCall(VecDestroy(&w)); 2968 PetscCall(VecConjugate(z)); 2969 if (v2 != v3) { 2970 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2971 } else { 2972 PetscCall(VecAXPY(v3, 1.0, z)); 2973 } 2974 PetscCall(VecDestroy(&z)); 2975 } 2976 PetscCall(VecLockReadPop(v1)); 2977 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2978 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2979 PetscFunctionReturn(PETSC_SUCCESS); 2980 } 2981 2982 /*@ 2983 MatGetFactorType - gets the type of factorization a matrix is 2984 2985 Not Collective 2986 2987 Input Parameter: 2988 . mat - the matrix 2989 2990 Output Parameter: 2991 . 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` 2992 2993 Level: intermediate 2994 2995 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2996 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2997 @*/ 2998 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2999 { 3000 PetscFunctionBegin; 3001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3002 PetscValidType(mat, 1); 3003 PetscAssertPointer(t, 2); 3004 *t = mat->factortype; 3005 PetscFunctionReturn(PETSC_SUCCESS); 3006 } 3007 3008 /*@ 3009 MatSetFactorType - sets the type of factorization a matrix is 3010 3011 Logically Collective 3012 3013 Input Parameters: 3014 + mat - the matrix 3015 - 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` 3016 3017 Level: intermediate 3018 3019 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3020 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3021 @*/ 3022 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3023 { 3024 PetscFunctionBegin; 3025 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3026 PetscValidType(mat, 1); 3027 mat->factortype = t; 3028 PetscFunctionReturn(PETSC_SUCCESS); 3029 } 3030 3031 /*@ 3032 MatGetInfo - Returns information about matrix storage (number of 3033 nonzeros, memory, etc.). 3034 3035 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3036 3037 Input Parameters: 3038 + mat - the matrix 3039 - 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) 3040 3041 Output Parameter: 3042 . info - matrix information context 3043 3044 Options Database Key: 3045 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3046 3047 Level: intermediate 3048 3049 Notes: 3050 The `MatInfo` context contains a variety of matrix data, including 3051 number of nonzeros allocated and used, number of mallocs during 3052 matrix assembly, etc. Additional information for factored matrices 3053 is provided (such as the fill ratio, number of mallocs during 3054 factorization, etc.). 3055 3056 Example: 3057 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3058 data within the `MatInfo` context. For example, 3059 .vb 3060 MatInfo info; 3061 Mat A; 3062 double mal, nz_a, nz_u; 3063 3064 MatGetInfo(A, MAT_LOCAL, &info); 3065 mal = info.mallocs; 3066 nz_a = info.nz_allocated; 3067 .ve 3068 3069 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3070 @*/ 3071 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3072 { 3073 PetscFunctionBegin; 3074 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3075 PetscValidType(mat, 1); 3076 PetscAssertPointer(info, 3); 3077 MatCheckPreallocated(mat, 1); 3078 PetscUseTypeMethod(mat, getinfo, flag, info); 3079 PetscFunctionReturn(PETSC_SUCCESS); 3080 } 3081 3082 /* 3083 This is used by external packages where it is not easy to get the info from the actual 3084 matrix factorization. 3085 */ 3086 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3087 { 3088 PetscFunctionBegin; 3089 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3090 PetscFunctionReturn(PETSC_SUCCESS); 3091 } 3092 3093 /*@ 3094 MatLUFactor - Performs in-place LU factorization of matrix. 3095 3096 Collective 3097 3098 Input Parameters: 3099 + mat - the matrix 3100 . row - row permutation 3101 . col - column permutation 3102 - info - options for factorization, includes 3103 .vb 3104 fill - expected fill as ratio of original fill. 3105 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3106 Run with the option -info to determine an optimal value to use 3107 .ve 3108 3109 Level: developer 3110 3111 Notes: 3112 Most users should employ the `KSP` interface for linear solvers 3113 instead of working directly with matrix algebra routines such as this. 3114 See, e.g., `KSPCreate()`. 3115 3116 This changes the state of the matrix to a factored matrix; it cannot be used 3117 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3118 3119 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3120 when not using `KSP`. 3121 3122 Fortran Note: 3123 A valid (non-null) `info` argument must be provided 3124 3125 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3126 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3127 @*/ 3128 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3129 { 3130 MatFactorInfo tinfo; 3131 3132 PetscFunctionBegin; 3133 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3134 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3135 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3136 if (info) PetscAssertPointer(info, 4); 3137 PetscValidType(mat, 1); 3138 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3139 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3140 MatCheckPreallocated(mat, 1); 3141 if (!info) { 3142 PetscCall(MatFactorInfoInitialize(&tinfo)); 3143 info = &tinfo; 3144 } 3145 3146 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3147 PetscUseTypeMethod(mat, lufactor, row, col, info); 3148 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3149 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3150 PetscFunctionReturn(PETSC_SUCCESS); 3151 } 3152 3153 /*@ 3154 MatILUFactor - Performs in-place ILU factorization of matrix. 3155 3156 Collective 3157 3158 Input Parameters: 3159 + mat - the matrix 3160 . row - row permutation 3161 . col - column permutation 3162 - info - structure containing 3163 .vb 3164 levels - number of levels of fill. 3165 expected fill - as ratio of original fill. 3166 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3167 missing diagonal entries) 3168 .ve 3169 3170 Level: developer 3171 3172 Notes: 3173 Most users should employ the `KSP` interface for linear solvers 3174 instead of working directly with matrix algebra routines such as this. 3175 See, e.g., `KSPCreate()`. 3176 3177 Probably really in-place only when level of fill is zero, otherwise allocates 3178 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3179 when not using `KSP`. 3180 3181 Fortran Note: 3182 A valid (non-null) `info` argument must be provided 3183 3184 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3185 @*/ 3186 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3187 { 3188 PetscFunctionBegin; 3189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3190 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3191 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3192 PetscAssertPointer(info, 4); 3193 PetscValidType(mat, 1); 3194 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3195 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3196 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3197 MatCheckPreallocated(mat, 1); 3198 3199 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3200 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3201 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3202 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3203 PetscFunctionReturn(PETSC_SUCCESS); 3204 } 3205 3206 /*@ 3207 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3208 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3209 3210 Collective 3211 3212 Input Parameters: 3213 + fact - the factor matrix obtained with `MatGetFactor()` 3214 . mat - the matrix 3215 . row - the row permutation 3216 . col - the column permutation 3217 - info - options for factorization, includes 3218 .vb 3219 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3220 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3221 .ve 3222 3223 Level: developer 3224 3225 Notes: 3226 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3227 3228 Most users should employ the simplified `KSP` interface for linear solvers 3229 instead of working directly with matrix algebra routines such as this. 3230 See, e.g., `KSPCreate()`. 3231 3232 Fortran Note: 3233 A valid (non-null) `info` argument must be provided 3234 3235 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3236 @*/ 3237 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3238 { 3239 MatFactorInfo tinfo; 3240 3241 PetscFunctionBegin; 3242 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3244 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3245 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3246 if (info) PetscAssertPointer(info, 5); 3247 PetscValidType(fact, 1); 3248 PetscValidType(mat, 2); 3249 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3250 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3251 MatCheckPreallocated(mat, 2); 3252 if (!info) { 3253 PetscCall(MatFactorInfoInitialize(&tinfo)); 3254 info = &tinfo; 3255 } 3256 3257 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3258 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3259 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3260 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3261 PetscFunctionReturn(PETSC_SUCCESS); 3262 } 3263 3264 /*@ 3265 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3266 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3267 3268 Collective 3269 3270 Input Parameters: 3271 + fact - the factor matrix obtained with `MatGetFactor()` 3272 . mat - the matrix 3273 - info - options for factorization 3274 3275 Level: developer 3276 3277 Notes: 3278 See `MatLUFactor()` for in-place factorization. See 3279 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3280 3281 Most users should employ the `KSP` interface for linear solvers 3282 instead of working directly with matrix algebra routines such as this. 3283 See, e.g., `KSPCreate()`. 3284 3285 Fortran Note: 3286 A valid (non-null) `info` argument must be provided 3287 3288 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3289 @*/ 3290 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3291 { 3292 MatFactorInfo tinfo; 3293 3294 PetscFunctionBegin; 3295 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3297 PetscValidType(fact, 1); 3298 PetscValidType(mat, 2); 3299 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3300 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, 3301 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3302 3303 MatCheckPreallocated(mat, 2); 3304 if (!info) { 3305 PetscCall(MatFactorInfoInitialize(&tinfo)); 3306 info = &tinfo; 3307 } 3308 3309 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3310 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3311 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3312 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3313 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3314 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3315 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3316 PetscFunctionReturn(PETSC_SUCCESS); 3317 } 3318 3319 /*@ 3320 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3321 symmetric matrix. 3322 3323 Collective 3324 3325 Input Parameters: 3326 + mat - the matrix 3327 . perm - row and column permutations 3328 - info - expected fill as ratio of original fill 3329 3330 Level: developer 3331 3332 Notes: 3333 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3334 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3335 3336 Most users should employ the `KSP` interface for linear solvers 3337 instead of working directly with matrix algebra routines such as this. 3338 See, e.g., `KSPCreate()`. 3339 3340 Fortran Note: 3341 A valid (non-null) `info` argument must be provided 3342 3343 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3344 `MatGetOrdering()` 3345 @*/ 3346 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3347 { 3348 MatFactorInfo tinfo; 3349 3350 PetscFunctionBegin; 3351 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3352 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3353 if (info) PetscAssertPointer(info, 3); 3354 PetscValidType(mat, 1); 3355 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3356 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3357 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3358 MatCheckPreallocated(mat, 1); 3359 if (!info) { 3360 PetscCall(MatFactorInfoInitialize(&tinfo)); 3361 info = &tinfo; 3362 } 3363 3364 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3365 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3366 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3367 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3368 PetscFunctionReturn(PETSC_SUCCESS); 3369 } 3370 3371 /*@ 3372 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3373 of a symmetric matrix. 3374 3375 Collective 3376 3377 Input Parameters: 3378 + fact - the factor matrix obtained with `MatGetFactor()` 3379 . mat - the matrix 3380 . perm - row and column permutations 3381 - info - options for factorization, includes 3382 .vb 3383 fill - expected fill as ratio of original fill. 3384 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3385 Run with the option -info to determine an optimal value to use 3386 .ve 3387 3388 Level: developer 3389 3390 Notes: 3391 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3392 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3393 3394 Most users should employ the `KSP` interface for linear solvers 3395 instead of working directly with matrix algebra routines such as this. 3396 See, e.g., `KSPCreate()`. 3397 3398 Fortran Note: 3399 A valid (non-null) `info` argument must be provided 3400 3401 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3402 `MatGetOrdering()` 3403 @*/ 3404 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3405 { 3406 MatFactorInfo tinfo; 3407 3408 PetscFunctionBegin; 3409 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3410 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3411 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3412 if (info) PetscAssertPointer(info, 4); 3413 PetscValidType(fact, 1); 3414 PetscValidType(mat, 2); 3415 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3416 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3417 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3418 MatCheckPreallocated(mat, 2); 3419 if (!info) { 3420 PetscCall(MatFactorInfoInitialize(&tinfo)); 3421 info = &tinfo; 3422 } 3423 3424 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3425 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3426 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3427 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3428 PetscFunctionReturn(PETSC_SUCCESS); 3429 } 3430 3431 /*@ 3432 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3433 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3434 `MatCholeskyFactorSymbolic()`. 3435 3436 Collective 3437 3438 Input Parameters: 3439 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3440 . mat - the initial matrix that is to be factored 3441 - info - options for factorization 3442 3443 Level: developer 3444 3445 Note: 3446 Most users should employ the `KSP` interface for linear solvers 3447 instead of working directly with matrix algebra routines such as this. 3448 See, e.g., `KSPCreate()`. 3449 3450 Fortran Note: 3451 A valid (non-null) `info` argument must be provided 3452 3453 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3454 @*/ 3455 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3456 { 3457 MatFactorInfo tinfo; 3458 3459 PetscFunctionBegin; 3460 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3461 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3462 PetscValidType(fact, 1); 3463 PetscValidType(mat, 2); 3464 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3465 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, 3466 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3467 MatCheckPreallocated(mat, 2); 3468 if (!info) { 3469 PetscCall(MatFactorInfoInitialize(&tinfo)); 3470 info = &tinfo; 3471 } 3472 3473 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3474 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3475 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3476 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3477 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3478 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3479 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3480 PetscFunctionReturn(PETSC_SUCCESS); 3481 } 3482 3483 /*@ 3484 MatQRFactor - Performs in-place QR factorization of matrix. 3485 3486 Collective 3487 3488 Input Parameters: 3489 + mat - the matrix 3490 . col - column permutation 3491 - info - options for factorization, includes 3492 .vb 3493 fill - expected fill as ratio of original fill. 3494 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3495 Run with the option -info to determine an optimal value to use 3496 .ve 3497 3498 Level: developer 3499 3500 Notes: 3501 Most users should employ the `KSP` interface for linear solvers 3502 instead of working directly with matrix algebra routines such as this. 3503 See, e.g., `KSPCreate()`. 3504 3505 This changes the state of the matrix to a factored matrix; it cannot be used 3506 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3507 3508 Fortran Note: 3509 A valid (non-null) `info` argument must be provided 3510 3511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3512 `MatSetUnfactored()` 3513 @*/ 3514 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3515 { 3516 PetscFunctionBegin; 3517 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3518 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3519 if (info) PetscAssertPointer(info, 3); 3520 PetscValidType(mat, 1); 3521 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3522 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3523 MatCheckPreallocated(mat, 1); 3524 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3525 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3526 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3527 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3528 PetscFunctionReturn(PETSC_SUCCESS); 3529 } 3530 3531 /*@ 3532 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3533 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3534 3535 Collective 3536 3537 Input Parameters: 3538 + fact - the factor matrix obtained with `MatGetFactor()` 3539 . mat - the matrix 3540 . col - column permutation 3541 - info - options for factorization, includes 3542 .vb 3543 fill - expected fill as ratio of original fill. 3544 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3545 Run with the option -info to determine an optimal value to use 3546 .ve 3547 3548 Level: developer 3549 3550 Note: 3551 Most users should employ the `KSP` interface for linear solvers 3552 instead of working directly with matrix algebra routines such as this. 3553 See, e.g., `KSPCreate()`. 3554 3555 Fortran Note: 3556 A valid (non-null) `info` argument must be provided 3557 3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3559 @*/ 3560 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3561 { 3562 MatFactorInfo tinfo; 3563 3564 PetscFunctionBegin; 3565 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3567 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3568 if (info) PetscAssertPointer(info, 4); 3569 PetscValidType(fact, 1); 3570 PetscValidType(mat, 2); 3571 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3572 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3573 MatCheckPreallocated(mat, 2); 3574 if (!info) { 3575 PetscCall(MatFactorInfoInitialize(&tinfo)); 3576 info = &tinfo; 3577 } 3578 3579 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3580 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3581 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3582 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3583 PetscFunctionReturn(PETSC_SUCCESS); 3584 } 3585 3586 /*@ 3587 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3588 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3589 3590 Collective 3591 3592 Input Parameters: 3593 + fact - the factor matrix obtained with `MatGetFactor()` 3594 . mat - the matrix 3595 - info - options for factorization 3596 3597 Level: developer 3598 3599 Notes: 3600 See `MatQRFactor()` for in-place factorization. 3601 3602 Most users should employ the `KSP` interface for linear solvers 3603 instead of working directly with matrix algebra routines such as this. 3604 See, e.g., `KSPCreate()`. 3605 3606 Fortran Note: 3607 A valid (non-null) `info` argument must be provided 3608 3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3610 @*/ 3611 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3612 { 3613 MatFactorInfo tinfo; 3614 3615 PetscFunctionBegin; 3616 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3617 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3618 PetscValidType(fact, 1); 3619 PetscValidType(mat, 2); 3620 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3621 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, 3622 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3623 3624 MatCheckPreallocated(mat, 2); 3625 if (!info) { 3626 PetscCall(MatFactorInfoInitialize(&tinfo)); 3627 info = &tinfo; 3628 } 3629 3630 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3631 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3632 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3633 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3634 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3635 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3636 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3637 PetscFunctionReturn(PETSC_SUCCESS); 3638 } 3639 3640 /*@ 3641 MatSolve - Solves $A x = b$, given a factored matrix. 3642 3643 Neighbor-wise Collective 3644 3645 Input Parameters: 3646 + mat - the factored matrix 3647 - b - the right-hand-side vector 3648 3649 Output Parameter: 3650 . x - the result vector 3651 3652 Level: developer 3653 3654 Notes: 3655 The vectors `b` and `x` cannot be the same. I.e., one cannot 3656 call `MatSolve`(A,x,x). 3657 3658 Most users should employ the `KSP` interface for linear solvers 3659 instead of working directly with matrix algebra routines such as this. 3660 See, e.g., `KSPCreate()`. 3661 3662 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3663 @*/ 3664 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3665 { 3666 PetscFunctionBegin; 3667 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3668 PetscValidType(mat, 1); 3669 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3670 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3671 PetscCheckSameComm(mat, 1, b, 2); 3672 PetscCheckSameComm(mat, 1, x, 3); 3673 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3674 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); 3675 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); 3676 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); 3677 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3678 MatCheckPreallocated(mat, 1); 3679 3680 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3681 PetscCall(VecFlag(x, mat->factorerrortype)); 3682 if (mat->factorerrortype) { 3683 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3684 } else PetscUseTypeMethod(mat, solve, b, x); 3685 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3686 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3687 PetscFunctionReturn(PETSC_SUCCESS); 3688 } 3689 3690 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3691 { 3692 Vec b, x; 3693 PetscInt N, i; 3694 PetscErrorCode (*f)(Mat, Vec, Vec); 3695 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3696 3697 PetscFunctionBegin; 3698 if (A->factorerrortype) { 3699 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3700 PetscCall(MatSetInf(X)); 3701 PetscFunctionReturn(PETSC_SUCCESS); 3702 } 3703 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3704 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3705 PetscCall(MatBoundToCPU(A, &Abound)); 3706 if (!Abound) { 3707 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3708 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3709 } 3710 #if PetscDefined(HAVE_CUDA) 3711 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3712 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3713 #elif PetscDefined(HAVE_HIP) 3714 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3715 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3716 #endif 3717 PetscCall(MatGetSize(B, NULL, &N)); 3718 for (i = 0; i < N; i++) { 3719 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3720 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3721 PetscCall((*f)(A, b, x)); 3722 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3723 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3724 } 3725 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3726 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3727 PetscFunctionReturn(PETSC_SUCCESS); 3728 } 3729 3730 /*@ 3731 MatMatSolve - Solves $A X = B$, given a factored matrix. 3732 3733 Neighbor-wise Collective 3734 3735 Input Parameters: 3736 + A - the factored matrix 3737 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3738 3739 Output Parameter: 3740 . X - the result matrix (dense matrix) 3741 3742 Level: developer 3743 3744 Note: 3745 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3746 otherwise, `B` and `X` cannot be the same. 3747 3748 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3749 @*/ 3750 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3751 { 3752 PetscFunctionBegin; 3753 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3754 PetscValidType(A, 1); 3755 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3756 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3757 PetscCheckSameComm(A, 1, B, 2); 3758 PetscCheckSameComm(A, 1, X, 3); 3759 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); 3760 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); 3761 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"); 3762 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3763 MatCheckPreallocated(A, 1); 3764 3765 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3766 if (!A->ops->matsolve) { 3767 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3768 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3769 } else PetscUseTypeMethod(A, matsolve, B, X); 3770 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3771 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3772 PetscFunctionReturn(PETSC_SUCCESS); 3773 } 3774 3775 /*@ 3776 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3777 3778 Neighbor-wise Collective 3779 3780 Input Parameters: 3781 + A - the factored matrix 3782 - B - the right-hand-side matrix (`MATDENSE` matrix) 3783 3784 Output Parameter: 3785 . X - the result matrix (dense matrix) 3786 3787 Level: developer 3788 3789 Note: 3790 The matrices `B` and `X` cannot be the same. I.e., one cannot 3791 call `MatMatSolveTranspose`(A,X,X). 3792 3793 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3794 @*/ 3795 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3796 { 3797 PetscFunctionBegin; 3798 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3799 PetscValidType(A, 1); 3800 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3801 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3802 PetscCheckSameComm(A, 1, B, 2); 3803 PetscCheckSameComm(A, 1, X, 3); 3804 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3805 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); 3806 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); 3807 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); 3808 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"); 3809 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3810 MatCheckPreallocated(A, 1); 3811 3812 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3813 if (!A->ops->matsolvetranspose) { 3814 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3815 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3816 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3817 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3818 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3819 PetscFunctionReturn(PETSC_SUCCESS); 3820 } 3821 3822 /*@ 3823 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3824 3825 Neighbor-wise Collective 3826 3827 Input Parameters: 3828 + A - the factored matrix 3829 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3830 3831 Output Parameter: 3832 . X - the result matrix (dense matrix) 3833 3834 Level: developer 3835 3836 Note: 3837 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 3838 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3839 3840 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3841 @*/ 3842 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3843 { 3844 PetscFunctionBegin; 3845 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3846 PetscValidType(A, 1); 3847 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3848 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3849 PetscCheckSameComm(A, 1, Bt, 2); 3850 PetscCheckSameComm(A, 1, X, 3); 3851 3852 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3853 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); 3854 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); 3855 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"); 3856 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3857 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3858 MatCheckPreallocated(A, 1); 3859 3860 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3861 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3862 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3863 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3864 PetscFunctionReturn(PETSC_SUCCESS); 3865 } 3866 3867 /*@ 3868 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3869 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3870 3871 Neighbor-wise Collective 3872 3873 Input Parameters: 3874 + mat - the factored matrix 3875 - b - the right-hand-side vector 3876 3877 Output Parameter: 3878 . x - the result vector 3879 3880 Level: developer 3881 3882 Notes: 3883 `MatSolve()` should be used for most applications, as it performs 3884 a forward solve followed by a backward solve. 3885 3886 The vectors `b` and `x` cannot be the same, i.e., one cannot 3887 call `MatForwardSolve`(A,x,x). 3888 3889 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3890 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3891 `MatForwardSolve()` solves $U^T*D y = b$, and 3892 `MatBackwardSolve()` solves $U x = y$. 3893 Thus they do not provide a symmetric preconditioner. 3894 3895 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3896 @*/ 3897 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3898 { 3899 PetscFunctionBegin; 3900 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3901 PetscValidType(mat, 1); 3902 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3903 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3904 PetscCheckSameComm(mat, 1, b, 2); 3905 PetscCheckSameComm(mat, 1, x, 3); 3906 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3907 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); 3908 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); 3909 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); 3910 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3911 MatCheckPreallocated(mat, 1); 3912 3913 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3914 PetscUseTypeMethod(mat, forwardsolve, b, x); 3915 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3916 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3917 PetscFunctionReturn(PETSC_SUCCESS); 3918 } 3919 3920 /*@ 3921 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3922 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3923 3924 Neighbor-wise Collective 3925 3926 Input Parameters: 3927 + mat - the factored matrix 3928 - b - the right-hand-side vector 3929 3930 Output Parameter: 3931 . x - the result vector 3932 3933 Level: developer 3934 3935 Notes: 3936 `MatSolve()` should be used for most applications, as it performs 3937 a forward solve followed by a backward solve. 3938 3939 The vectors `b` and `x` cannot be the same. I.e., one cannot 3940 call `MatBackwardSolve`(A,x,x). 3941 3942 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3943 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3944 `MatForwardSolve()` solves $U^T*D y = b$, and 3945 `MatBackwardSolve()` solves $U x = y$. 3946 Thus they do not provide a symmetric preconditioner. 3947 3948 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3949 @*/ 3950 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3951 { 3952 PetscFunctionBegin; 3953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3954 PetscValidType(mat, 1); 3955 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3956 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3957 PetscCheckSameComm(mat, 1, b, 2); 3958 PetscCheckSameComm(mat, 1, x, 3); 3959 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3960 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); 3961 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); 3962 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); 3963 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3964 MatCheckPreallocated(mat, 1); 3965 3966 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3967 PetscUseTypeMethod(mat, backwardsolve, b, x); 3968 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3969 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3970 PetscFunctionReturn(PETSC_SUCCESS); 3971 } 3972 3973 /*@ 3974 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3975 3976 Neighbor-wise Collective 3977 3978 Input Parameters: 3979 + mat - the factored matrix 3980 . b - the right-hand-side vector 3981 - y - the vector to be added to 3982 3983 Output Parameter: 3984 . x - the result vector 3985 3986 Level: developer 3987 3988 Note: 3989 The vectors `b` and `x` cannot be the same. I.e., one cannot 3990 call `MatSolveAdd`(A,x,y,x). 3991 3992 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3993 @*/ 3994 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3995 { 3996 PetscScalar one = 1.0; 3997 Vec tmp; 3998 3999 PetscFunctionBegin; 4000 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4001 PetscValidType(mat, 1); 4002 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4003 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4004 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4005 PetscCheckSameComm(mat, 1, b, 2); 4006 PetscCheckSameComm(mat, 1, y, 3); 4007 PetscCheckSameComm(mat, 1, x, 4); 4008 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4009 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); 4010 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); 4011 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); 4012 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); 4013 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); 4014 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4015 MatCheckPreallocated(mat, 1); 4016 4017 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4018 PetscCall(VecFlag(x, mat->factorerrortype)); 4019 if (mat->factorerrortype) { 4020 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4021 } else if (mat->ops->solveadd) { 4022 PetscUseTypeMethod(mat, solveadd, b, y, x); 4023 } else { 4024 /* do the solve then the add manually */ 4025 if (x != y) { 4026 PetscCall(MatSolve(mat, b, x)); 4027 PetscCall(VecAXPY(x, one, y)); 4028 } else { 4029 PetscCall(VecDuplicate(x, &tmp)); 4030 PetscCall(VecCopy(x, tmp)); 4031 PetscCall(MatSolve(mat, b, x)); 4032 PetscCall(VecAXPY(x, one, tmp)); 4033 PetscCall(VecDestroy(&tmp)); 4034 } 4035 } 4036 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4037 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4038 PetscFunctionReturn(PETSC_SUCCESS); 4039 } 4040 4041 /*@ 4042 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4043 4044 Neighbor-wise Collective 4045 4046 Input Parameters: 4047 + mat - the factored matrix 4048 - b - the right-hand-side vector 4049 4050 Output Parameter: 4051 . x - the result vector 4052 4053 Level: developer 4054 4055 Notes: 4056 The vectors `b` and `x` cannot be the same. I.e., one cannot 4057 call `MatSolveTranspose`(A,x,x). 4058 4059 Most users should employ the `KSP` interface for linear solvers 4060 instead of working directly with matrix algebra routines such as this. 4061 See, e.g., `KSPCreate()`. 4062 4063 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4064 @*/ 4065 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4066 { 4067 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4068 4069 PetscFunctionBegin; 4070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4071 PetscValidType(mat, 1); 4072 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4073 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4074 PetscCheckSameComm(mat, 1, b, 2); 4075 PetscCheckSameComm(mat, 1, x, 3); 4076 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4077 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); 4078 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); 4079 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4080 MatCheckPreallocated(mat, 1); 4081 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4082 PetscCall(VecFlag(x, mat->factorerrortype)); 4083 if (mat->factorerrortype) { 4084 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4085 } else { 4086 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4087 PetscCall((*f)(mat, b, x)); 4088 } 4089 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4090 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4091 PetscFunctionReturn(PETSC_SUCCESS); 4092 } 4093 4094 /*@ 4095 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4096 factored matrix. 4097 4098 Neighbor-wise Collective 4099 4100 Input Parameters: 4101 + mat - the factored matrix 4102 . b - the right-hand-side vector 4103 - y - the vector to be added to 4104 4105 Output Parameter: 4106 . x - the result vector 4107 4108 Level: developer 4109 4110 Note: 4111 The vectors `b` and `x` cannot be the same. I.e., one cannot 4112 call `MatSolveTransposeAdd`(A,x,y,x). 4113 4114 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4115 @*/ 4116 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4117 { 4118 PetscScalar one = 1.0; 4119 Vec tmp; 4120 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4121 4122 PetscFunctionBegin; 4123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4124 PetscValidType(mat, 1); 4125 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4126 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4127 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4128 PetscCheckSameComm(mat, 1, b, 2); 4129 PetscCheckSameComm(mat, 1, y, 3); 4130 PetscCheckSameComm(mat, 1, x, 4); 4131 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4132 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); 4133 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); 4134 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); 4135 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); 4136 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4137 MatCheckPreallocated(mat, 1); 4138 4139 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4140 PetscCall(VecFlag(x, mat->factorerrortype)); 4141 if (mat->factorerrortype) { 4142 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4143 } else if (f) { 4144 PetscCall((*f)(mat, b, y, x)); 4145 } else { 4146 /* do the solve then the add manually */ 4147 if (x != y) { 4148 PetscCall(MatSolveTranspose(mat, b, x)); 4149 PetscCall(VecAXPY(x, one, y)); 4150 } else { 4151 PetscCall(VecDuplicate(x, &tmp)); 4152 PetscCall(VecCopy(x, tmp)); 4153 PetscCall(MatSolveTranspose(mat, b, x)); 4154 PetscCall(VecAXPY(x, one, tmp)); 4155 PetscCall(VecDestroy(&tmp)); 4156 } 4157 } 4158 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4159 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4160 PetscFunctionReturn(PETSC_SUCCESS); 4161 } 4162 4163 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4164 /*@ 4165 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4166 4167 Neighbor-wise Collective 4168 4169 Input Parameters: 4170 + mat - the matrix 4171 . b - the right-hand side 4172 . omega - the relaxation factor 4173 . flag - flag indicating the type of SOR (see below) 4174 . shift - diagonal shift 4175 . its - the number of iterations 4176 - lits - the number of local iterations 4177 4178 Output Parameter: 4179 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4180 4181 SOR Flags: 4182 + `SOR_FORWARD_SWEEP` - forward SOR 4183 . `SOR_BACKWARD_SWEEP` - backward SOR 4184 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4185 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4186 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4187 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4188 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4189 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4190 upper/lower triangular part of matrix to 4191 vector (with omega) 4192 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4193 4194 Level: developer 4195 4196 Notes: 4197 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4198 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4199 on each processor. 4200 4201 Application programmers will not generally use `MatSOR()` directly, 4202 but instead will employ the `KSP`/`PC` interface. 4203 4204 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4205 4206 Most users should employ the `KSP` interface for linear solvers 4207 instead of working directly with matrix algebra routines such as this. 4208 See, e.g., `KSPCreate()`. 4209 4210 Vectors `x` and `b` CANNOT be the same 4211 4212 The flags are implemented as bitwise inclusive or operations. 4213 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4214 to specify a zero initial guess for SSOR. 4215 4216 Developer Note: 4217 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4218 4219 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4220 @*/ 4221 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4222 { 4223 PetscFunctionBegin; 4224 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4225 PetscValidType(mat, 1); 4226 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4227 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4228 PetscCheckSameComm(mat, 1, b, 2); 4229 PetscCheckSameComm(mat, 1, x, 8); 4230 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4231 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4232 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); 4233 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); 4234 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); 4235 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4236 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4237 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4238 4239 MatCheckPreallocated(mat, 1); 4240 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4241 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4242 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4243 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4244 PetscFunctionReturn(PETSC_SUCCESS); 4245 } 4246 4247 /* 4248 Default matrix copy routine. 4249 */ 4250 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4251 { 4252 PetscInt i, rstart = 0, rend = 0, nz; 4253 const PetscInt *cwork; 4254 const PetscScalar *vwork; 4255 4256 PetscFunctionBegin; 4257 if (B->assembled) PetscCall(MatZeroEntries(B)); 4258 if (str == SAME_NONZERO_PATTERN) { 4259 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4260 for (i = rstart; i < rend; i++) { 4261 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4262 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4263 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4264 } 4265 } else { 4266 PetscCall(MatAYPX(B, 0.0, A, str)); 4267 } 4268 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4269 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4270 PetscFunctionReturn(PETSC_SUCCESS); 4271 } 4272 4273 /*@ 4274 MatCopy - Copies a matrix to another matrix. 4275 4276 Collective 4277 4278 Input Parameters: 4279 + A - the matrix 4280 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4281 4282 Output Parameter: 4283 . B - where the copy is put 4284 4285 Level: intermediate 4286 4287 Notes: 4288 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4289 4290 `MatCopy()` copies the matrix entries of a matrix to another existing 4291 matrix (after first zeroing the second matrix). A related routine is 4292 `MatConvert()`, which first creates a new matrix and then copies the data. 4293 4294 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4295 @*/ 4296 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4297 { 4298 PetscInt i; 4299 4300 PetscFunctionBegin; 4301 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4302 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4303 PetscValidType(A, 1); 4304 PetscValidType(B, 2); 4305 PetscCheckSameComm(A, 1, B, 2); 4306 MatCheckPreallocated(B, 2); 4307 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4308 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4309 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, 4310 A->cmap->N, B->cmap->N); 4311 MatCheckPreallocated(A, 1); 4312 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4313 4314 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4315 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4316 else PetscCall(MatCopy_Basic(A, B, str)); 4317 4318 B->stencil.dim = A->stencil.dim; 4319 B->stencil.noc = A->stencil.noc; 4320 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4321 B->stencil.dims[i] = A->stencil.dims[i]; 4322 B->stencil.starts[i] = A->stencil.starts[i]; 4323 } 4324 4325 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4326 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4327 PetscFunctionReturn(PETSC_SUCCESS); 4328 } 4329 4330 /*@ 4331 MatConvert - Converts a matrix to another matrix, either of the same 4332 or different type. 4333 4334 Collective 4335 4336 Input Parameters: 4337 + mat - the matrix 4338 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4339 same type as the original matrix. 4340 - reuse - denotes if the destination matrix is to be created or reused. 4341 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 4342 `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). 4343 4344 Output Parameter: 4345 . M - pointer to place new matrix 4346 4347 Level: intermediate 4348 4349 Notes: 4350 `MatConvert()` first creates a new matrix and then copies the data from 4351 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4352 entries of one matrix to another already existing matrix context. 4353 4354 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4355 the MPI communicator of the generated matrix is always the same as the communicator 4356 of the input matrix. 4357 4358 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4359 @*/ 4360 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4361 { 4362 PetscBool sametype, issame, flg; 4363 PetscBool3 issymmetric, ishermitian; 4364 char convname[256], mtype[256]; 4365 Mat B; 4366 4367 PetscFunctionBegin; 4368 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4369 PetscValidType(mat, 1); 4370 PetscAssertPointer(M, 4); 4371 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4372 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4373 MatCheckPreallocated(mat, 1); 4374 4375 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4376 if (flg) newtype = mtype; 4377 4378 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4379 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4380 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4381 if (reuse == MAT_REUSE_MATRIX) { 4382 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4383 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4384 } 4385 4386 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4387 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4388 PetscFunctionReturn(PETSC_SUCCESS); 4389 } 4390 4391 /* Cache Mat options because some converters use MatHeaderReplace */ 4392 issymmetric = mat->symmetric; 4393 ishermitian = mat->hermitian; 4394 4395 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4396 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4397 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4398 } else { 4399 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4400 const char *prefix[3] = {"seq", "mpi", ""}; 4401 PetscInt i; 4402 /* 4403 Order of precedence: 4404 0) See if newtype is a superclass of the current matrix. 4405 1) See if a specialized converter is known to the current matrix. 4406 2) See if a specialized converter is known to the desired matrix class. 4407 3) See if a good general converter is registered for the desired class 4408 (as of 6/27/03 only MATMPIADJ falls into this category). 4409 4) See if a good general converter is known for the current matrix. 4410 5) Use a really basic converter. 4411 */ 4412 4413 /* 0) See if newtype is a superclass of the current matrix. 4414 i.e mat is mpiaij and newtype is aij */ 4415 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4416 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4417 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4418 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4419 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4420 if (flg) { 4421 if (reuse == MAT_INPLACE_MATRIX) { 4422 PetscCall(PetscInfo(mat, "Early return\n")); 4423 PetscFunctionReturn(PETSC_SUCCESS); 4424 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4425 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4426 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4427 PetscFunctionReturn(PETSC_SUCCESS); 4428 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4429 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4430 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4431 PetscFunctionReturn(PETSC_SUCCESS); 4432 } 4433 } 4434 } 4435 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4436 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4437 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4438 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4439 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4440 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4441 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4443 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4444 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4445 if (conv) goto foundconv; 4446 } 4447 4448 /* 2) See if a specialized converter is known to the desired matrix class. */ 4449 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4450 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4451 PetscCall(MatSetType(B, newtype)); 4452 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4453 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4454 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4455 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4456 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4457 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4458 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4459 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4460 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4461 if (conv) { 4462 PetscCall(MatDestroy(&B)); 4463 goto foundconv; 4464 } 4465 } 4466 4467 /* 3) See if a good general converter is registered for the desired class */ 4468 conv = B->ops->convertfrom; 4469 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4470 PetscCall(MatDestroy(&B)); 4471 if (conv) goto foundconv; 4472 4473 /* 4) See if a good general converter is known for the current matrix */ 4474 if (mat->ops->convert) conv = mat->ops->convert; 4475 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4476 if (conv) goto foundconv; 4477 4478 /* 5) Use a really basic converter. */ 4479 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4480 conv = MatConvert_Basic; 4481 4482 foundconv: 4483 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4484 PetscCall((*conv)(mat, newtype, reuse, M)); 4485 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4486 /* the block sizes must be same if the mappings are copied over */ 4487 (*M)->rmap->bs = mat->rmap->bs; 4488 (*M)->cmap->bs = mat->cmap->bs; 4489 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4490 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4491 (*M)->rmap->mapping = mat->rmap->mapping; 4492 (*M)->cmap->mapping = mat->cmap->mapping; 4493 } 4494 (*M)->stencil.dim = mat->stencil.dim; 4495 (*M)->stencil.noc = mat->stencil.noc; 4496 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4497 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4498 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4499 } 4500 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4501 } 4502 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4503 4504 /* Copy Mat options */ 4505 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4506 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4507 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4508 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4509 PetscFunctionReturn(PETSC_SUCCESS); 4510 } 4511 4512 /*@ 4513 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4514 4515 Not Collective 4516 4517 Input Parameter: 4518 . mat - the matrix, must be a factored matrix 4519 4520 Output Parameter: 4521 . type - the string name of the package (do not free this string) 4522 4523 Level: intermediate 4524 4525 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4526 @*/ 4527 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4528 { 4529 PetscErrorCode (*conv)(Mat, MatSolverType *); 4530 4531 PetscFunctionBegin; 4532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4533 PetscValidType(mat, 1); 4534 PetscAssertPointer(type, 2); 4535 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4536 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4537 if (conv) PetscCall((*conv)(mat, type)); 4538 else *type = MATSOLVERPETSC; 4539 PetscFunctionReturn(PETSC_SUCCESS); 4540 } 4541 4542 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4543 struct _MatSolverTypeForSpecifcType { 4544 MatType mtype; 4545 /* no entry for MAT_FACTOR_NONE */ 4546 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4547 MatSolverTypeForSpecifcType next; 4548 }; 4549 4550 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4551 struct _MatSolverTypeHolder { 4552 char *name; 4553 MatSolverTypeForSpecifcType handlers; 4554 MatSolverTypeHolder next; 4555 }; 4556 4557 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4558 4559 /*@C 4560 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4561 4562 Logically Collective, No Fortran Support 4563 4564 Input Parameters: 4565 + package - name of the package, for example `petsc` or `superlu` 4566 . mtype - the matrix type that works with this package 4567 . ftype - the type of factorization supported by the package 4568 - createfactor - routine that will create the factored matrix ready to be used 4569 4570 Level: developer 4571 4572 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4573 `MatGetFactor()` 4574 @*/ 4575 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4576 { 4577 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4578 PetscBool flg; 4579 MatSolverTypeForSpecifcType inext, iprev = NULL; 4580 4581 PetscFunctionBegin; 4582 PetscCall(MatInitializePackage()); 4583 if (!next) { 4584 PetscCall(PetscNew(&MatSolverTypeHolders)); 4585 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4586 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4587 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4588 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4589 PetscFunctionReturn(PETSC_SUCCESS); 4590 } 4591 while (next) { 4592 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4593 if (flg) { 4594 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4595 inext = next->handlers; 4596 while (inext) { 4597 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4598 if (flg) { 4599 inext->createfactor[(int)ftype - 1] = createfactor; 4600 PetscFunctionReturn(PETSC_SUCCESS); 4601 } 4602 iprev = inext; 4603 inext = inext->next; 4604 } 4605 PetscCall(PetscNew(&iprev->next)); 4606 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4607 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4608 PetscFunctionReturn(PETSC_SUCCESS); 4609 } 4610 prev = next; 4611 next = next->next; 4612 } 4613 PetscCall(PetscNew(&prev->next)); 4614 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4615 PetscCall(PetscNew(&prev->next->handlers)); 4616 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4617 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4618 PetscFunctionReturn(PETSC_SUCCESS); 4619 } 4620 4621 /*@C 4622 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4623 4624 Input Parameters: 4625 + 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 4626 . ftype - the type of factorization supported by the type 4627 - mtype - the matrix type that works with this type 4628 4629 Output Parameters: 4630 + foundtype - `PETSC_TRUE` if the type was registered 4631 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4632 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4633 4634 Calling sequence of `createfactor`: 4635 + A - the matrix providing the factor matrix 4636 . ftype - the `MatFactorType` of the factor requested 4637 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4638 4639 Level: developer 4640 4641 Note: 4642 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4643 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4644 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4645 4646 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4647 `MatInitializePackage()` 4648 @*/ 4649 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4650 { 4651 MatSolverTypeHolder next = MatSolverTypeHolders; 4652 PetscBool flg; 4653 MatSolverTypeForSpecifcType inext; 4654 4655 PetscFunctionBegin; 4656 if (foundtype) *foundtype = PETSC_FALSE; 4657 if (foundmtype) *foundmtype = PETSC_FALSE; 4658 if (createfactor) *createfactor = NULL; 4659 4660 if (type) { 4661 while (next) { 4662 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4663 if (flg) { 4664 if (foundtype) *foundtype = PETSC_TRUE; 4665 inext = next->handlers; 4666 while (inext) { 4667 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4668 if (flg) { 4669 if (foundmtype) *foundmtype = PETSC_TRUE; 4670 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4671 PetscFunctionReturn(PETSC_SUCCESS); 4672 } 4673 inext = inext->next; 4674 } 4675 } 4676 next = next->next; 4677 } 4678 } else { 4679 while (next) { 4680 inext = next->handlers; 4681 while (inext) { 4682 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4683 if (flg && inext->createfactor[(int)ftype - 1]) { 4684 if (foundtype) *foundtype = PETSC_TRUE; 4685 if (foundmtype) *foundmtype = PETSC_TRUE; 4686 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4687 PetscFunctionReturn(PETSC_SUCCESS); 4688 } 4689 inext = inext->next; 4690 } 4691 next = next->next; 4692 } 4693 /* try with base classes inext->mtype */ 4694 next = MatSolverTypeHolders; 4695 while (next) { 4696 inext = next->handlers; 4697 while (inext) { 4698 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4699 if (flg && inext->createfactor[(int)ftype - 1]) { 4700 if (foundtype) *foundtype = PETSC_TRUE; 4701 if (foundmtype) *foundmtype = PETSC_TRUE; 4702 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4703 PetscFunctionReturn(PETSC_SUCCESS); 4704 } 4705 inext = inext->next; 4706 } 4707 next = next->next; 4708 } 4709 } 4710 PetscFunctionReturn(PETSC_SUCCESS); 4711 } 4712 4713 PetscErrorCode MatSolverTypeDestroy(void) 4714 { 4715 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4716 MatSolverTypeForSpecifcType inext, iprev; 4717 4718 PetscFunctionBegin; 4719 while (next) { 4720 PetscCall(PetscFree(next->name)); 4721 inext = next->handlers; 4722 while (inext) { 4723 PetscCall(PetscFree(inext->mtype)); 4724 iprev = inext; 4725 inext = inext->next; 4726 PetscCall(PetscFree(iprev)); 4727 } 4728 prev = next; 4729 next = next->next; 4730 PetscCall(PetscFree(prev)); 4731 } 4732 MatSolverTypeHolders = NULL; 4733 PetscFunctionReturn(PETSC_SUCCESS); 4734 } 4735 4736 /*@ 4737 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4738 4739 Logically Collective 4740 4741 Input Parameter: 4742 . mat - the matrix 4743 4744 Output Parameter: 4745 . flg - `PETSC_TRUE` if uses the ordering 4746 4747 Level: developer 4748 4749 Note: 4750 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4751 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4752 4753 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4754 @*/ 4755 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4756 { 4757 PetscFunctionBegin; 4758 *flg = mat->canuseordering; 4759 PetscFunctionReturn(PETSC_SUCCESS); 4760 } 4761 4762 /*@ 4763 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4764 4765 Logically Collective 4766 4767 Input Parameters: 4768 + mat - the matrix obtained with `MatGetFactor()` 4769 - ftype - the factorization type to be used 4770 4771 Output Parameter: 4772 . otype - the preferred ordering type 4773 4774 Level: developer 4775 4776 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4777 @*/ 4778 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4779 { 4780 PetscFunctionBegin; 4781 *otype = mat->preferredordering[ftype]; 4782 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4783 PetscFunctionReturn(PETSC_SUCCESS); 4784 } 4785 4786 /*@ 4787 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4788 4789 Collective 4790 4791 Input Parameters: 4792 + mat - the matrix 4793 . 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 4794 the other criteria is returned 4795 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4796 4797 Output Parameter: 4798 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4799 4800 Options Database Keys: 4801 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4802 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4803 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4804 4805 Level: intermediate 4806 4807 Notes: 4808 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4809 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4810 4811 Users usually access the factorization solvers via `KSP` 4812 4813 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4814 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 4815 4816 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4817 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4818 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4819 4820 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4821 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4822 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4823 4824 Developer Note: 4825 This should actually be called `MatCreateFactor()` since it creates a new factor object 4826 4827 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4828 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4829 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4830 @*/ 4831 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4832 { 4833 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4834 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4835 4836 PetscFunctionBegin; 4837 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4838 PetscValidType(mat, 1); 4839 4840 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4841 MatCheckPreallocated(mat, 1); 4842 4843 PetscCall(MatIsShell(mat, &shell)); 4844 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4845 if (hasop) { 4846 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4847 PetscFunctionReturn(PETSC_SUCCESS); 4848 } 4849 4850 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4851 if (!foundtype) { 4852 if (type) { 4853 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], 4854 ((PetscObject)mat)->type_name, type); 4855 } else { 4856 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); 4857 } 4858 } 4859 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4860 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); 4861 4862 PetscCall((*conv)(mat, ftype, f)); 4863 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4864 PetscFunctionReturn(PETSC_SUCCESS); 4865 } 4866 4867 /*@ 4868 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4869 4870 Not Collective 4871 4872 Input Parameters: 4873 + mat - the matrix 4874 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4875 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4876 4877 Output Parameter: 4878 . flg - PETSC_TRUE if the factorization is available 4879 4880 Level: intermediate 4881 4882 Notes: 4883 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4884 such as pastix, superlu, mumps etc. 4885 4886 PETSc must have been ./configure to use the external solver, using the option --download-package 4887 4888 Developer Note: 4889 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4890 4891 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4892 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4893 @*/ 4894 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4895 { 4896 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4897 4898 PetscFunctionBegin; 4899 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4900 PetscAssertPointer(flg, 4); 4901 4902 *flg = PETSC_FALSE; 4903 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4904 4905 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4906 MatCheckPreallocated(mat, 1); 4907 4908 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4909 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4910 PetscFunctionReturn(PETSC_SUCCESS); 4911 } 4912 4913 /*@ 4914 MatDuplicate - Duplicates a matrix including the non-zero structure. 4915 4916 Collective 4917 4918 Input Parameters: 4919 + mat - the matrix 4920 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4921 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4922 4923 Output Parameter: 4924 . M - pointer to place new matrix 4925 4926 Level: intermediate 4927 4928 Notes: 4929 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4930 4931 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4932 4933 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. 4934 4935 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4936 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4937 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4938 4939 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4940 @*/ 4941 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4942 { 4943 Mat B; 4944 VecType vtype; 4945 PetscInt i; 4946 PetscObject dm, container_h, container_d; 4947 void (*viewf)(void); 4948 4949 PetscFunctionBegin; 4950 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4951 PetscValidType(mat, 1); 4952 PetscAssertPointer(M, 3); 4953 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4954 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4955 MatCheckPreallocated(mat, 1); 4956 4957 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4958 PetscUseTypeMethod(mat, duplicate, op, M); 4959 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4960 B = *M; 4961 4962 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4963 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4964 PetscCall(MatGetVecType(mat, &vtype)); 4965 PetscCall(MatSetVecType(B, vtype)); 4966 4967 B->stencil.dim = mat->stencil.dim; 4968 B->stencil.noc = mat->stencil.noc; 4969 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4970 B->stencil.dims[i] = mat->stencil.dims[i]; 4971 B->stencil.starts[i] = mat->stencil.starts[i]; 4972 } 4973 4974 B->nooffproczerorows = mat->nooffproczerorows; 4975 B->nooffprocentries = mat->nooffprocentries; 4976 4977 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4978 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4979 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4980 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4981 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4982 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4983 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4984 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4985 PetscFunctionReturn(PETSC_SUCCESS); 4986 } 4987 4988 /*@ 4989 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4990 4991 Logically Collective 4992 4993 Input Parameter: 4994 . mat - the matrix 4995 4996 Output Parameter: 4997 . v - the diagonal of the matrix 4998 4999 Level: intermediate 5000 5001 Note: 5002 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5003 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5004 is larger than `ndiag`, the values of the remaining entries are unspecified. 5005 5006 Currently only correct in parallel for square matrices. 5007 5008 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5009 @*/ 5010 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5011 { 5012 PetscFunctionBegin; 5013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5014 PetscValidType(mat, 1); 5015 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5016 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5017 MatCheckPreallocated(mat, 1); 5018 if (PetscDefined(USE_DEBUG)) { 5019 PetscInt nv, row, col, ndiag; 5020 5021 PetscCall(VecGetLocalSize(v, &nv)); 5022 PetscCall(MatGetLocalSize(mat, &row, &col)); 5023 ndiag = PetscMin(row, col); 5024 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); 5025 } 5026 5027 PetscUseTypeMethod(mat, getdiagonal, v); 5028 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5029 PetscFunctionReturn(PETSC_SUCCESS); 5030 } 5031 5032 /*@ 5033 MatGetRowMin - Gets the minimum value (of the real part) of each 5034 row of the matrix 5035 5036 Logically Collective 5037 5038 Input Parameter: 5039 . mat - the matrix 5040 5041 Output Parameters: 5042 + v - the vector for storing the maximums 5043 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5044 5045 Level: intermediate 5046 5047 Note: 5048 The result of this call are the same as if one converted the matrix to dense format 5049 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5050 5051 This code is only implemented for a couple of matrix formats. 5052 5053 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5054 `MatGetRowMax()` 5055 @*/ 5056 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5057 { 5058 PetscFunctionBegin; 5059 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5060 PetscValidType(mat, 1); 5061 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5062 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5063 5064 if (!mat->cmap->N) { 5065 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5066 if (idx) { 5067 PetscInt i, m = mat->rmap->n; 5068 for (i = 0; i < m; i++) idx[i] = -1; 5069 } 5070 } else { 5071 MatCheckPreallocated(mat, 1); 5072 } 5073 PetscUseTypeMethod(mat, getrowmin, v, idx); 5074 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5075 PetscFunctionReturn(PETSC_SUCCESS); 5076 } 5077 5078 /*@ 5079 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5080 row of the matrix 5081 5082 Logically Collective 5083 5084 Input Parameter: 5085 . mat - the matrix 5086 5087 Output Parameters: 5088 + v - the vector for storing the minimums 5089 - idx - the indices of the column found for each row (or `NULL` if not needed) 5090 5091 Level: intermediate 5092 5093 Notes: 5094 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5095 row is 0 (the first column). 5096 5097 This code is only implemented for a couple of matrix formats. 5098 5099 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5100 @*/ 5101 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5102 { 5103 PetscFunctionBegin; 5104 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5105 PetscValidType(mat, 1); 5106 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5107 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5108 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5109 5110 if (!mat->cmap->N) { 5111 PetscCall(VecSet(v, 0.0)); 5112 if (idx) { 5113 PetscInt i, m = mat->rmap->n; 5114 for (i = 0; i < m; i++) idx[i] = -1; 5115 } 5116 } else { 5117 MatCheckPreallocated(mat, 1); 5118 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5119 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5120 } 5121 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5122 PetscFunctionReturn(PETSC_SUCCESS); 5123 } 5124 5125 /*@ 5126 MatGetRowMax - Gets the maximum value (of the real part) of each 5127 row of the matrix 5128 5129 Logically Collective 5130 5131 Input Parameter: 5132 . mat - the matrix 5133 5134 Output Parameters: 5135 + v - the vector for storing the maximums 5136 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5137 5138 Level: intermediate 5139 5140 Notes: 5141 The result of this call are the same as if one converted the matrix to dense format 5142 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5143 5144 This code is only implemented for a couple of matrix formats. 5145 5146 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5147 @*/ 5148 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5149 { 5150 PetscFunctionBegin; 5151 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5152 PetscValidType(mat, 1); 5153 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5154 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5155 5156 if (!mat->cmap->N) { 5157 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5158 if (idx) { 5159 PetscInt i, m = mat->rmap->n; 5160 for (i = 0; i < m; i++) idx[i] = -1; 5161 } 5162 } else { 5163 MatCheckPreallocated(mat, 1); 5164 PetscUseTypeMethod(mat, getrowmax, v, idx); 5165 } 5166 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5167 PetscFunctionReturn(PETSC_SUCCESS); 5168 } 5169 5170 /*@ 5171 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5172 row of the matrix 5173 5174 Logically Collective 5175 5176 Input Parameter: 5177 . mat - the matrix 5178 5179 Output Parameters: 5180 + v - the vector for storing the maximums 5181 - idx - the indices of the column found for each row (or `NULL` if not needed) 5182 5183 Level: intermediate 5184 5185 Notes: 5186 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5187 row is 0 (the first column). 5188 5189 This code is only implemented for a couple of matrix formats. 5190 5191 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5192 @*/ 5193 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5194 { 5195 PetscFunctionBegin; 5196 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5197 PetscValidType(mat, 1); 5198 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5199 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5200 5201 if (!mat->cmap->N) { 5202 PetscCall(VecSet(v, 0.0)); 5203 if (idx) { 5204 PetscInt i, m = mat->rmap->n; 5205 for (i = 0; i < m; i++) idx[i] = -1; 5206 } 5207 } else { 5208 MatCheckPreallocated(mat, 1); 5209 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5210 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5211 } 5212 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5213 PetscFunctionReturn(PETSC_SUCCESS); 5214 } 5215 5216 /*@ 5217 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5218 5219 Logically Collective 5220 5221 Input Parameter: 5222 . mat - the matrix 5223 5224 Output Parameter: 5225 . v - the vector for storing the sum 5226 5227 Level: intermediate 5228 5229 This code is only implemented for a couple of matrix formats. 5230 5231 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5232 @*/ 5233 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5234 { 5235 PetscFunctionBegin; 5236 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5237 PetscValidType(mat, 1); 5238 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5239 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5240 5241 if (!mat->cmap->N) { 5242 PetscCall(VecSet(v, 0.0)); 5243 } else { 5244 MatCheckPreallocated(mat, 1); 5245 PetscUseTypeMethod(mat, getrowsumabs, v); 5246 } 5247 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5248 PetscFunctionReturn(PETSC_SUCCESS); 5249 } 5250 5251 /*@ 5252 MatGetRowSum - Gets the sum of each row of the matrix 5253 5254 Logically or Neighborhood Collective 5255 5256 Input Parameter: 5257 . mat - the matrix 5258 5259 Output Parameter: 5260 . v - the vector for storing the sum of rows 5261 5262 Level: intermediate 5263 5264 Note: 5265 This code is slow since it is not currently specialized for different formats 5266 5267 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5268 @*/ 5269 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5270 { 5271 Vec ones; 5272 5273 PetscFunctionBegin; 5274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5275 PetscValidType(mat, 1); 5276 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5277 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5278 MatCheckPreallocated(mat, 1); 5279 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5280 PetscCall(VecSet(ones, 1.)); 5281 PetscCall(MatMult(mat, ones, v)); 5282 PetscCall(VecDestroy(&ones)); 5283 PetscFunctionReturn(PETSC_SUCCESS); 5284 } 5285 5286 /*@ 5287 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5288 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5289 5290 Collective 5291 5292 Input Parameter: 5293 . mat - the matrix to provide the transpose 5294 5295 Output Parameter: 5296 . 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 5297 5298 Level: advanced 5299 5300 Note: 5301 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 5302 routine allows bypassing that call. 5303 5304 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5305 @*/ 5306 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5307 { 5308 MatParentState *rb = NULL; 5309 5310 PetscFunctionBegin; 5311 PetscCall(PetscNew(&rb)); 5312 rb->id = ((PetscObject)mat)->id; 5313 rb->state = 0; 5314 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5315 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5316 PetscFunctionReturn(PETSC_SUCCESS); 5317 } 5318 5319 /*@ 5320 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5321 5322 Collective 5323 5324 Input Parameters: 5325 + mat - the matrix to transpose 5326 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5327 5328 Output Parameter: 5329 . B - the transpose of the matrix 5330 5331 Level: intermediate 5332 5333 Notes: 5334 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5335 5336 `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 5337 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5338 5339 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. 5340 5341 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5342 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5343 5344 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5345 5346 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5347 5348 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5349 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5350 @*/ 5351 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5352 { 5353 PetscContainer rB = NULL; 5354 MatParentState *rb = NULL; 5355 5356 PetscFunctionBegin; 5357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5358 PetscValidType(mat, 1); 5359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5361 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5362 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5363 MatCheckPreallocated(mat, 1); 5364 if (reuse == MAT_REUSE_MATRIX) { 5365 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5366 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5367 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5368 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5369 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5370 } 5371 5372 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5373 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5374 PetscUseTypeMethod(mat, transpose, reuse, B); 5375 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5376 } 5377 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5378 5379 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5380 if (reuse != MAT_INPLACE_MATRIX) { 5381 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5382 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5383 rb->state = ((PetscObject)mat)->state; 5384 rb->nonzerostate = mat->nonzerostate; 5385 } 5386 PetscFunctionReturn(PETSC_SUCCESS); 5387 } 5388 5389 /*@ 5390 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5391 5392 Collective 5393 5394 Input Parameter: 5395 . A - the matrix to transpose 5396 5397 Output Parameter: 5398 . 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 5399 numerical portion. 5400 5401 Level: intermediate 5402 5403 Note: 5404 This is not supported for many matrix types, use `MatTranspose()` in those cases 5405 5406 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5407 @*/ 5408 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5409 { 5410 PetscFunctionBegin; 5411 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5412 PetscValidType(A, 1); 5413 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5414 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5415 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5416 PetscUseTypeMethod(A, transposesymbolic, B); 5417 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5418 5419 PetscCall(MatTransposeSetPrecursor(A, *B)); 5420 PetscFunctionReturn(PETSC_SUCCESS); 5421 } 5422 5423 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5424 { 5425 PetscContainer rB; 5426 MatParentState *rb; 5427 5428 PetscFunctionBegin; 5429 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5430 PetscValidType(A, 1); 5431 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5432 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5433 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5434 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5435 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5436 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5437 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5438 PetscFunctionReturn(PETSC_SUCCESS); 5439 } 5440 5441 /*@ 5442 MatIsTranspose - Test whether a matrix is another one's transpose, 5443 or its own, in which case it tests symmetry. 5444 5445 Collective 5446 5447 Input Parameters: 5448 + A - the matrix to test 5449 . B - the matrix to test against, this can equal the first parameter 5450 - tol - tolerance, differences between entries smaller than this are counted as zero 5451 5452 Output Parameter: 5453 . flg - the result 5454 5455 Level: intermediate 5456 5457 Notes: 5458 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5459 test involves parallel copies of the block off-diagonal parts of the matrix. 5460 5461 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5462 @*/ 5463 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5464 { 5465 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5466 5467 PetscFunctionBegin; 5468 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5469 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5470 PetscAssertPointer(flg, 4); 5471 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5472 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5473 *flg = PETSC_FALSE; 5474 if (f && g) { 5475 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5476 PetscCall((*f)(A, B, tol, flg)); 5477 } else { 5478 MatType mattype; 5479 5480 PetscCall(MatGetType(f ? B : A, &mattype)); 5481 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5482 } 5483 PetscFunctionReturn(PETSC_SUCCESS); 5484 } 5485 5486 /*@ 5487 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5488 5489 Collective 5490 5491 Input Parameters: 5492 + mat - the matrix to transpose and complex conjugate 5493 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5494 5495 Output Parameter: 5496 . B - the Hermitian transpose 5497 5498 Level: intermediate 5499 5500 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5501 @*/ 5502 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5503 { 5504 PetscFunctionBegin; 5505 PetscCall(MatTranspose(mat, reuse, B)); 5506 #if defined(PETSC_USE_COMPLEX) 5507 PetscCall(MatConjugate(*B)); 5508 #endif 5509 PetscFunctionReturn(PETSC_SUCCESS); 5510 } 5511 5512 /*@ 5513 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5514 5515 Collective 5516 5517 Input Parameters: 5518 + A - the matrix to test 5519 . B - the matrix to test against, this can equal the first parameter 5520 - tol - tolerance, differences between entries smaller than this are counted as zero 5521 5522 Output Parameter: 5523 . flg - the result 5524 5525 Level: intermediate 5526 5527 Notes: 5528 Only available for `MATAIJ` matrices. 5529 5530 The sequential algorithm 5531 has a running time of the order of the number of nonzeros; the parallel 5532 test involves parallel copies of the block off-diagonal parts of the matrix. 5533 5534 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5535 @*/ 5536 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5537 { 5538 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5539 5540 PetscFunctionBegin; 5541 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5542 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5543 PetscAssertPointer(flg, 4); 5544 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5545 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5546 if (f && g) { 5547 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5548 PetscCall((*f)(A, B, tol, flg)); 5549 } 5550 PetscFunctionReturn(PETSC_SUCCESS); 5551 } 5552 5553 /*@ 5554 MatPermute - Creates a new matrix with rows and columns permuted from the 5555 original. 5556 5557 Collective 5558 5559 Input Parameters: 5560 + mat - the matrix to permute 5561 . row - row permutation, each processor supplies only the permutation for its rows 5562 - col - column permutation, each processor supplies only the permutation for its columns 5563 5564 Output Parameter: 5565 . B - the permuted matrix 5566 5567 Level: advanced 5568 5569 Note: 5570 The index sets map from row/col of permuted matrix to row/col of original matrix. 5571 The index sets should be on the same communicator as mat and have the same local sizes. 5572 5573 Developer Note: 5574 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5575 exploit the fact that row and col are permutations, consider implementing the 5576 more general `MatCreateSubMatrix()` instead. 5577 5578 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5579 @*/ 5580 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5581 { 5582 PetscFunctionBegin; 5583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5584 PetscValidType(mat, 1); 5585 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5586 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5587 PetscAssertPointer(B, 4); 5588 PetscCheckSameComm(mat, 1, row, 2); 5589 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5590 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5591 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5592 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5593 MatCheckPreallocated(mat, 1); 5594 5595 if (mat->ops->permute) { 5596 PetscUseTypeMethod(mat, permute, row, col, B); 5597 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5598 } else { 5599 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5600 } 5601 PetscFunctionReturn(PETSC_SUCCESS); 5602 } 5603 5604 /*@ 5605 MatEqual - Compares two matrices. 5606 5607 Collective 5608 5609 Input Parameters: 5610 + A - the first matrix 5611 - B - the second matrix 5612 5613 Output Parameter: 5614 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5615 5616 Level: intermediate 5617 5618 Note: 5619 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing the results of several matrix-vector product 5620 using several randomly created vectors, see `MatMultEqual()`. 5621 5622 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5623 @*/ 5624 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5625 { 5626 PetscFunctionBegin; 5627 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5628 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5629 PetscValidType(A, 1); 5630 PetscValidType(B, 2); 5631 PetscAssertPointer(flg, 3); 5632 PetscCheckSameComm(A, 1, B, 2); 5633 MatCheckPreallocated(A, 1); 5634 MatCheckPreallocated(B, 2); 5635 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5636 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5637 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, 5638 B->cmap->N); 5639 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5640 PetscUseTypeMethod(A, equal, B, flg); 5641 } else { 5642 PetscCall(MatMultEqual(A, B, 10, flg)); 5643 } 5644 PetscFunctionReturn(PETSC_SUCCESS); 5645 } 5646 5647 /*@ 5648 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5649 matrices that are stored as vectors. Either of the two scaling 5650 matrices can be `NULL`. 5651 5652 Collective 5653 5654 Input Parameters: 5655 + mat - the matrix to be scaled 5656 . l - the left scaling vector (or `NULL`) 5657 - r - the right scaling vector (or `NULL`) 5658 5659 Level: intermediate 5660 5661 Note: 5662 `MatDiagonalScale()` computes $A = LAR$, where 5663 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5664 The L scales the rows of the matrix, the R scales the columns of the matrix. 5665 5666 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5667 @*/ 5668 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5669 { 5670 PetscFunctionBegin; 5671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5672 PetscValidType(mat, 1); 5673 if (l) { 5674 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5675 PetscCheckSameComm(mat, 1, l, 2); 5676 } 5677 if (r) { 5678 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5679 PetscCheckSameComm(mat, 1, r, 3); 5680 } 5681 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5682 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5683 MatCheckPreallocated(mat, 1); 5684 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5685 5686 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5687 PetscUseTypeMethod(mat, diagonalscale, l, r); 5688 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5689 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5690 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5691 PetscFunctionReturn(PETSC_SUCCESS); 5692 } 5693 5694 /*@ 5695 MatScale - Scales all elements of a matrix by a given number. 5696 5697 Logically Collective 5698 5699 Input Parameters: 5700 + mat - the matrix to be scaled 5701 - a - the scaling value 5702 5703 Level: intermediate 5704 5705 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5706 @*/ 5707 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5708 { 5709 PetscFunctionBegin; 5710 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5711 PetscValidType(mat, 1); 5712 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5713 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5714 PetscValidLogicalCollectiveScalar(mat, a, 2); 5715 MatCheckPreallocated(mat, 1); 5716 5717 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5718 if (a != (PetscScalar)1.0) { 5719 PetscUseTypeMethod(mat, scale, a); 5720 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5721 } 5722 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5723 PetscFunctionReturn(PETSC_SUCCESS); 5724 } 5725 5726 /*@ 5727 MatNorm - Calculates various norms of a matrix. 5728 5729 Collective 5730 5731 Input Parameters: 5732 + mat - the matrix 5733 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5734 5735 Output Parameter: 5736 . nrm - the resulting norm 5737 5738 Level: intermediate 5739 5740 .seealso: [](ch_matrices), `Mat` 5741 @*/ 5742 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5743 { 5744 PetscFunctionBegin; 5745 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5746 PetscValidType(mat, 1); 5747 PetscAssertPointer(nrm, 3); 5748 5749 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5750 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5751 MatCheckPreallocated(mat, 1); 5752 5753 PetscUseTypeMethod(mat, norm, type, nrm); 5754 PetscFunctionReturn(PETSC_SUCCESS); 5755 } 5756 5757 /* 5758 This variable is used to prevent counting of MatAssemblyBegin() that 5759 are called from within a MatAssemblyEnd(). 5760 */ 5761 static PetscInt MatAssemblyEnd_InUse = 0; 5762 /*@ 5763 MatAssemblyBegin - Begins assembling the matrix. This routine should 5764 be called after completing all calls to `MatSetValues()`. 5765 5766 Collective 5767 5768 Input Parameters: 5769 + mat - the matrix 5770 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5771 5772 Level: beginner 5773 5774 Notes: 5775 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5776 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5777 5778 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5779 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5780 using the matrix. 5781 5782 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5783 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 5784 a global collective operation requiring all processes that share the matrix. 5785 5786 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5787 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5788 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5789 5790 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5791 @*/ 5792 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5793 { 5794 PetscFunctionBegin; 5795 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5796 PetscValidType(mat, 1); 5797 MatCheckPreallocated(mat, 1); 5798 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5799 if (mat->assembled) { 5800 mat->was_assembled = PETSC_TRUE; 5801 mat->assembled = PETSC_FALSE; 5802 } 5803 5804 if (!MatAssemblyEnd_InUse) { 5805 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5806 PetscTryTypeMethod(mat, assemblybegin, type); 5807 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5808 } else PetscTryTypeMethod(mat, assemblybegin, type); 5809 PetscFunctionReturn(PETSC_SUCCESS); 5810 } 5811 5812 /*@ 5813 MatAssembled - Indicates if a matrix has been assembled and is ready for 5814 use; for example, in matrix-vector product. 5815 5816 Not Collective 5817 5818 Input Parameter: 5819 . mat - the matrix 5820 5821 Output Parameter: 5822 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5823 5824 Level: advanced 5825 5826 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5827 @*/ 5828 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5829 { 5830 PetscFunctionBegin; 5831 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5832 PetscAssertPointer(assembled, 2); 5833 *assembled = mat->assembled; 5834 PetscFunctionReturn(PETSC_SUCCESS); 5835 } 5836 5837 /*@ 5838 MatAssemblyEnd - Completes assembling the matrix. This routine should 5839 be called after `MatAssemblyBegin()`. 5840 5841 Collective 5842 5843 Input Parameters: 5844 + mat - the matrix 5845 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5846 5847 Options Database Keys: 5848 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5849 . -mat_view ::ascii_info_detail - Prints more detailed info 5850 . -mat_view - Prints matrix in ASCII format 5851 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5852 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5853 . -display <name> - Sets display name (default is host) 5854 . -draw_pause <sec> - Sets number of seconds to pause after display 5855 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5856 . -viewer_socket_machine <machine> - Machine to use for socket 5857 . -viewer_socket_port <port> - Port number to use for socket 5858 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5859 5860 Level: beginner 5861 5862 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5863 @*/ 5864 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5865 { 5866 static PetscInt inassm = 0; 5867 PetscBool flg = PETSC_FALSE; 5868 5869 PetscFunctionBegin; 5870 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5871 PetscValidType(mat, 1); 5872 5873 inassm++; 5874 MatAssemblyEnd_InUse++; 5875 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5876 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5877 PetscTryTypeMethod(mat, assemblyend, type); 5878 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5879 } else PetscTryTypeMethod(mat, assemblyend, type); 5880 5881 /* Flush assembly is not a true assembly */ 5882 if (type != MAT_FLUSH_ASSEMBLY) { 5883 if (mat->num_ass) { 5884 if (!mat->symmetry_eternal) { 5885 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5886 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5887 } 5888 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5889 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5890 } 5891 mat->num_ass++; 5892 mat->assembled = PETSC_TRUE; 5893 mat->ass_nonzerostate = mat->nonzerostate; 5894 } 5895 5896 mat->insertmode = NOT_SET_VALUES; 5897 MatAssemblyEnd_InUse--; 5898 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5899 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5900 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5901 5902 if (mat->checksymmetryonassembly) { 5903 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5904 if (flg) { 5905 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5906 } else { 5907 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5908 } 5909 } 5910 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5911 } 5912 inassm--; 5913 PetscFunctionReturn(PETSC_SUCCESS); 5914 } 5915 5916 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5917 /*@ 5918 MatSetOption - Sets a parameter option for a matrix. Some options 5919 may be specific to certain storage formats. Some options 5920 determine how values will be inserted (or added). Sorted, 5921 row-oriented input will generally assemble the fastest. The default 5922 is row-oriented. 5923 5924 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5925 5926 Input Parameters: 5927 + mat - the matrix 5928 . op - the option, one of those listed below (and possibly others), 5929 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5930 5931 Options Describing Matrix Structure: 5932 + `MAT_SPD` - symmetric positive definite 5933 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5934 . `MAT_HERMITIAN` - transpose is the complex conjugation 5935 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5936 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5937 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5938 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5939 5940 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5941 do not need to be computed (usually at a high cost) 5942 5943 Options For Use with `MatSetValues()`: 5944 Insert a logically dense subblock, which can be 5945 . `MAT_ROW_ORIENTED` - row-oriented (default) 5946 5947 These options reflect the data you pass in with `MatSetValues()`; it has 5948 nothing to do with how the data is stored internally in the matrix 5949 data structure. 5950 5951 When (re)assembling a matrix, we can restrict the input for 5952 efficiency/debugging purposes. These options include 5953 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5954 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5955 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5956 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5957 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5958 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5959 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5960 performance for very large process counts. 5961 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5962 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5963 functions, instead sending only neighbor messages. 5964 5965 Level: intermediate 5966 5967 Notes: 5968 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5969 5970 Some options are relevant only for particular matrix types and 5971 are thus ignored by others. Other options are not supported by 5972 certain matrix types and will generate an error message if set. 5973 5974 If using Fortran to compute a matrix, one may need to 5975 use the column-oriented option (or convert to the row-oriented 5976 format). 5977 5978 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5979 that would generate a new entry in the nonzero structure is instead 5980 ignored. Thus, if memory has not already been allocated for this particular 5981 data, then the insertion is ignored. For dense matrices, in which 5982 the entire array is allocated, no entries are ever ignored. 5983 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5984 5985 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5986 that would generate a new entry in the nonzero structure instead produces 5987 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 5988 5989 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5990 that would generate a new entry that has not been preallocated will 5991 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5992 only.) This is a useful flag when debugging matrix memory preallocation. 5993 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5994 5995 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5996 other processors should be dropped, rather than stashed. 5997 This is useful if you know that the "owning" processor is also 5998 always generating the correct matrix entries, so that PETSc need 5999 not transfer duplicate entries generated on another processor. 6000 6001 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6002 searches during matrix assembly. When this flag is set, the hash table 6003 is created during the first matrix assembly. This hash table is 6004 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6005 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6006 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6007 supported by `MATMPIBAIJ` format only. 6008 6009 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6010 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6011 6012 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6013 a zero location in the matrix 6014 6015 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6016 6017 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6018 zero row routines and thus improves performance for very large process counts. 6019 6020 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6021 part of the matrix (since they should match the upper triangular part). 6022 6023 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6024 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6025 with finite difference schemes with non-periodic boundary conditions. 6026 6027 Developer Note: 6028 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6029 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6030 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6031 not changed. 6032 6033 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6034 @*/ 6035 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6036 { 6037 PetscFunctionBegin; 6038 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6039 if (op > 0) { 6040 PetscValidLogicalCollectiveEnum(mat, op, 2); 6041 PetscValidLogicalCollectiveBool(mat, flg, 3); 6042 } 6043 6044 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); 6045 6046 switch (op) { 6047 case MAT_FORCE_DIAGONAL_ENTRIES: 6048 mat->force_diagonals = flg; 6049 PetscFunctionReturn(PETSC_SUCCESS); 6050 case MAT_NO_OFF_PROC_ENTRIES: 6051 mat->nooffprocentries = flg; 6052 PetscFunctionReturn(PETSC_SUCCESS); 6053 case MAT_SUBSET_OFF_PROC_ENTRIES: 6054 mat->assembly_subset = flg; 6055 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6056 #if !defined(PETSC_HAVE_MPIUNI) 6057 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6058 #endif 6059 mat->stash.first_assembly_done = PETSC_FALSE; 6060 } 6061 PetscFunctionReturn(PETSC_SUCCESS); 6062 case MAT_NO_OFF_PROC_ZERO_ROWS: 6063 mat->nooffproczerorows = flg; 6064 PetscFunctionReturn(PETSC_SUCCESS); 6065 case MAT_SPD: 6066 if (flg) { 6067 mat->spd = PETSC_BOOL3_TRUE; 6068 mat->symmetric = PETSC_BOOL3_TRUE; 6069 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6070 } else { 6071 mat->spd = PETSC_BOOL3_FALSE; 6072 } 6073 break; 6074 case MAT_SYMMETRIC: 6075 mat->symmetric = PetscBoolToBool3(flg); 6076 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6077 #if !defined(PETSC_USE_COMPLEX) 6078 mat->hermitian = PetscBoolToBool3(flg); 6079 #endif 6080 break; 6081 case MAT_HERMITIAN: 6082 mat->hermitian = PetscBoolToBool3(flg); 6083 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6084 #if !defined(PETSC_USE_COMPLEX) 6085 mat->symmetric = PetscBoolToBool3(flg); 6086 #endif 6087 break; 6088 case MAT_STRUCTURALLY_SYMMETRIC: 6089 mat->structurally_symmetric = PetscBoolToBool3(flg); 6090 break; 6091 case MAT_SYMMETRY_ETERNAL: 6092 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"); 6093 mat->symmetry_eternal = flg; 6094 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6095 break; 6096 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6097 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"); 6098 mat->structural_symmetry_eternal = flg; 6099 break; 6100 case MAT_SPD_ETERNAL: 6101 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"); 6102 mat->spd_eternal = flg; 6103 if (flg) { 6104 mat->structural_symmetry_eternal = PETSC_TRUE; 6105 mat->symmetry_eternal = PETSC_TRUE; 6106 } 6107 break; 6108 case MAT_STRUCTURE_ONLY: 6109 mat->structure_only = flg; 6110 break; 6111 case MAT_SORTED_FULL: 6112 mat->sortedfull = flg; 6113 break; 6114 default: 6115 break; 6116 } 6117 PetscTryTypeMethod(mat, setoption, op, flg); 6118 PetscFunctionReturn(PETSC_SUCCESS); 6119 } 6120 6121 /*@ 6122 MatGetOption - Gets a parameter option that has been set for a matrix. 6123 6124 Logically Collective 6125 6126 Input Parameters: 6127 + mat - the matrix 6128 - op - the option, this only responds to certain options, check the code for which ones 6129 6130 Output Parameter: 6131 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6132 6133 Level: intermediate 6134 6135 Notes: 6136 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6137 6138 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6139 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6140 6141 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6142 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6143 @*/ 6144 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6145 { 6146 PetscFunctionBegin; 6147 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6148 PetscValidType(mat, 1); 6149 6150 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); 6151 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()"); 6152 6153 switch (op) { 6154 case MAT_NO_OFF_PROC_ENTRIES: 6155 *flg = mat->nooffprocentries; 6156 break; 6157 case MAT_NO_OFF_PROC_ZERO_ROWS: 6158 *flg = mat->nooffproczerorows; 6159 break; 6160 case MAT_SYMMETRIC: 6161 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6162 break; 6163 case MAT_HERMITIAN: 6164 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6165 break; 6166 case MAT_STRUCTURALLY_SYMMETRIC: 6167 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6168 break; 6169 case MAT_SPD: 6170 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6171 break; 6172 case MAT_SYMMETRY_ETERNAL: 6173 *flg = mat->symmetry_eternal; 6174 break; 6175 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6176 *flg = mat->symmetry_eternal; 6177 break; 6178 default: 6179 break; 6180 } 6181 PetscFunctionReturn(PETSC_SUCCESS); 6182 } 6183 6184 /*@ 6185 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6186 this routine retains the old nonzero structure. 6187 6188 Logically Collective 6189 6190 Input Parameter: 6191 . mat - the matrix 6192 6193 Level: intermediate 6194 6195 Note: 6196 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. 6197 See the Performance chapter of the users manual for information on preallocating matrices. 6198 6199 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6200 @*/ 6201 PetscErrorCode MatZeroEntries(Mat mat) 6202 { 6203 PetscFunctionBegin; 6204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6205 PetscValidType(mat, 1); 6206 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6207 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"); 6208 MatCheckPreallocated(mat, 1); 6209 6210 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6211 PetscUseTypeMethod(mat, zeroentries); 6212 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6214 PetscFunctionReturn(PETSC_SUCCESS); 6215 } 6216 6217 /*@ 6218 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6219 of a set of rows and columns of a matrix. 6220 6221 Collective 6222 6223 Input Parameters: 6224 + mat - the matrix 6225 . numRows - the number of rows/columns to zero 6226 . rows - the global row indices 6227 . diag - value put in the diagonal of the eliminated rows 6228 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6229 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6230 6231 Level: intermediate 6232 6233 Notes: 6234 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6235 6236 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6237 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 6238 6239 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6240 Krylov method to take advantage of the known solution on the zeroed rows. 6241 6242 For the parallel case, all processes that share the matrix (i.e., 6243 those in the communicator used for matrix creation) MUST call this 6244 routine, regardless of whether any rows being zeroed are owned by 6245 them. 6246 6247 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6248 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 6249 missing. 6250 6251 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6252 list only rows local to itself). 6253 6254 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6255 6256 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6257 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6258 @*/ 6259 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6260 { 6261 PetscFunctionBegin; 6262 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6263 PetscValidType(mat, 1); 6264 if (numRows) PetscAssertPointer(rows, 3); 6265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6266 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6267 MatCheckPreallocated(mat, 1); 6268 6269 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6270 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6271 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6272 PetscFunctionReturn(PETSC_SUCCESS); 6273 } 6274 6275 /*@ 6276 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6277 of a set of rows and columns of a matrix. 6278 6279 Collective 6280 6281 Input Parameters: 6282 + mat - the matrix 6283 . is - the rows to zero 6284 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6285 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6286 - b - optional vector of right-hand side, that will be adjusted by provided solution 6287 6288 Level: intermediate 6289 6290 Note: 6291 See `MatZeroRowsColumns()` for details on how this routine operates. 6292 6293 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6294 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6295 @*/ 6296 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6297 { 6298 PetscInt numRows; 6299 const PetscInt *rows; 6300 6301 PetscFunctionBegin; 6302 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6303 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6304 PetscValidType(mat, 1); 6305 PetscValidType(is, 2); 6306 PetscCall(ISGetLocalSize(is, &numRows)); 6307 PetscCall(ISGetIndices(is, &rows)); 6308 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6309 PetscCall(ISRestoreIndices(is, &rows)); 6310 PetscFunctionReturn(PETSC_SUCCESS); 6311 } 6312 6313 /*@ 6314 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6315 of a set of rows of a matrix. 6316 6317 Collective 6318 6319 Input Parameters: 6320 + mat - the matrix 6321 . numRows - the number of rows to zero 6322 . rows - the global row indices 6323 . diag - value put in the diagonal of the zeroed rows 6324 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6325 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6326 6327 Level: intermediate 6328 6329 Notes: 6330 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6331 6332 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6333 6334 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6335 Krylov method to take advantage of the known solution on the zeroed rows. 6336 6337 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) 6338 from the matrix. 6339 6340 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6341 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6342 formats this does not alter the nonzero structure. 6343 6344 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6345 of the matrix is not changed the values are 6346 merely zeroed. 6347 6348 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6349 formats can optionally remove the main diagonal entry from the 6350 nonzero structure as well, by passing 0.0 as the final argument). 6351 6352 For the parallel case, all processes that share the matrix (i.e., 6353 those in the communicator used for matrix creation) MUST call this 6354 routine, regardless of whether any rows being zeroed are owned by 6355 them. 6356 6357 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6358 list only rows local to itself). 6359 6360 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6361 owns that are to be zeroed. This saves a global synchronization in the implementation. 6362 6363 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6364 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6365 @*/ 6366 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6367 { 6368 PetscFunctionBegin; 6369 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6370 PetscValidType(mat, 1); 6371 if (numRows) PetscAssertPointer(rows, 3); 6372 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6373 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6374 MatCheckPreallocated(mat, 1); 6375 6376 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6377 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6378 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6379 PetscFunctionReturn(PETSC_SUCCESS); 6380 } 6381 6382 /*@ 6383 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6384 of a set of rows of a matrix indicated by an `IS` 6385 6386 Collective 6387 6388 Input Parameters: 6389 + mat - the matrix 6390 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6391 . diag - value put in all diagonals of eliminated rows 6392 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6393 - b - optional vector of right-hand side, that will be adjusted by provided solution 6394 6395 Level: intermediate 6396 6397 Note: 6398 See `MatZeroRows()` for details on how this routine operates. 6399 6400 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6401 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6402 @*/ 6403 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6404 { 6405 PetscInt numRows = 0; 6406 const PetscInt *rows = NULL; 6407 6408 PetscFunctionBegin; 6409 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6410 PetscValidType(mat, 1); 6411 if (is) { 6412 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6413 PetscCall(ISGetLocalSize(is, &numRows)); 6414 PetscCall(ISGetIndices(is, &rows)); 6415 } 6416 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6417 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6418 PetscFunctionReturn(PETSC_SUCCESS); 6419 } 6420 6421 /*@ 6422 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6423 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6424 6425 Collective 6426 6427 Input Parameters: 6428 + mat - the matrix 6429 . numRows - the number of rows to remove 6430 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6431 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6432 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6433 - b - optional vector of right-hand side, that will be adjusted by provided solution 6434 6435 Level: intermediate 6436 6437 Notes: 6438 See `MatZeroRows()` for details on how this routine operates. 6439 6440 The grid coordinates are across the entire grid, not just the local portion 6441 6442 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6443 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6444 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6445 `DM_BOUNDARY_PERIODIC` boundary type. 6446 6447 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 6448 a single value per point) you can skip filling those indices. 6449 6450 Fortran Note: 6451 `idxm` and `idxn` should be declared as 6452 .vb 6453 MatStencil idxm(4, m) 6454 .ve 6455 and the values inserted using 6456 .vb 6457 idxm(MatStencil_i, 1) = i 6458 idxm(MatStencil_j, 1) = j 6459 idxm(MatStencil_k, 1) = k 6460 idxm(MatStencil_c, 1) = c 6461 etc 6462 .ve 6463 6464 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6465 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6466 @*/ 6467 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6468 { 6469 PetscInt dim = mat->stencil.dim; 6470 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6471 PetscInt *dims = mat->stencil.dims + 1; 6472 PetscInt *starts = mat->stencil.starts; 6473 PetscInt *dxm = (PetscInt *)rows; 6474 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6475 6476 PetscFunctionBegin; 6477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6478 PetscValidType(mat, 1); 6479 if (numRows) PetscAssertPointer(rows, 3); 6480 6481 PetscCall(PetscMalloc1(numRows, &jdxm)); 6482 for (i = 0; i < numRows; ++i) { 6483 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6484 for (j = 0; j < 3 - sdim; ++j) dxm++; 6485 /* Local index in X dir */ 6486 tmp = *dxm++ - starts[0]; 6487 /* Loop over remaining dimensions */ 6488 for (j = 0; j < dim - 1; ++j) { 6489 /* If nonlocal, set index to be negative */ 6490 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6491 /* Update local index */ 6492 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6493 } 6494 /* Skip component slot if necessary */ 6495 if (mat->stencil.noc) dxm++; 6496 /* Local row number */ 6497 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6498 } 6499 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6500 PetscCall(PetscFree(jdxm)); 6501 PetscFunctionReturn(PETSC_SUCCESS); 6502 } 6503 6504 /*@ 6505 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6506 of a set of rows and columns of a matrix. 6507 6508 Collective 6509 6510 Input Parameters: 6511 + mat - the matrix 6512 . numRows - the number of rows/columns to remove 6513 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6514 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6515 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6516 - b - optional vector of right-hand side, that will be adjusted by provided solution 6517 6518 Level: intermediate 6519 6520 Notes: 6521 See `MatZeroRowsColumns()` for details on how this routine operates. 6522 6523 The grid coordinates are across the entire grid, not just the local portion 6524 6525 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6526 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6527 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6528 `DM_BOUNDARY_PERIODIC` boundary type. 6529 6530 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 6531 a single value per point) you can skip filling those indices. 6532 6533 Fortran Note: 6534 `idxm` and `idxn` should be declared as 6535 .vb 6536 MatStencil idxm(4, m) 6537 .ve 6538 and the values inserted using 6539 .vb 6540 idxm(MatStencil_i, 1) = i 6541 idxm(MatStencil_j, 1) = j 6542 idxm(MatStencil_k, 1) = k 6543 idxm(MatStencil_c, 1) = c 6544 etc 6545 .ve 6546 6547 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6548 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6549 @*/ 6550 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6551 { 6552 PetscInt dim = mat->stencil.dim; 6553 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6554 PetscInt *dims = mat->stencil.dims + 1; 6555 PetscInt *starts = mat->stencil.starts; 6556 PetscInt *dxm = (PetscInt *)rows; 6557 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6558 6559 PetscFunctionBegin; 6560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6561 PetscValidType(mat, 1); 6562 if (numRows) PetscAssertPointer(rows, 3); 6563 6564 PetscCall(PetscMalloc1(numRows, &jdxm)); 6565 for (i = 0; i < numRows; ++i) { 6566 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6567 for (j = 0; j < 3 - sdim; ++j) dxm++; 6568 /* Local index in X dir */ 6569 tmp = *dxm++ - starts[0]; 6570 /* Loop over remaining dimensions */ 6571 for (j = 0; j < dim - 1; ++j) { 6572 /* If nonlocal, set index to be negative */ 6573 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6574 /* Update local index */ 6575 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6576 } 6577 /* Skip component slot if necessary */ 6578 if (mat->stencil.noc) dxm++; 6579 /* Local row number */ 6580 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6581 } 6582 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6583 PetscCall(PetscFree(jdxm)); 6584 PetscFunctionReturn(PETSC_SUCCESS); 6585 } 6586 6587 /*@ 6588 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6589 of a set of rows of a matrix; using local numbering of rows. 6590 6591 Collective 6592 6593 Input Parameters: 6594 + mat - the matrix 6595 . numRows - the number of rows to remove 6596 . rows - the local row indices 6597 . diag - value put in all diagonals of eliminated rows 6598 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6599 - b - optional vector of right-hand side, that will be adjusted by provided solution 6600 6601 Level: intermediate 6602 6603 Notes: 6604 Before calling `MatZeroRowsLocal()`, the user must first set the 6605 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6606 6607 See `MatZeroRows()` for details on how this routine operates. 6608 6609 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6610 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6611 @*/ 6612 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6613 { 6614 PetscFunctionBegin; 6615 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6616 PetscValidType(mat, 1); 6617 if (numRows) PetscAssertPointer(rows, 3); 6618 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6619 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6620 MatCheckPreallocated(mat, 1); 6621 6622 if (mat->ops->zerorowslocal) { 6623 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6624 } else { 6625 IS is, newis; 6626 const PetscInt *newRows; 6627 6628 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6629 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6630 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6631 PetscCall(ISGetIndices(newis, &newRows)); 6632 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6633 PetscCall(ISRestoreIndices(newis, &newRows)); 6634 PetscCall(ISDestroy(&newis)); 6635 PetscCall(ISDestroy(&is)); 6636 } 6637 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6638 PetscFunctionReturn(PETSC_SUCCESS); 6639 } 6640 6641 /*@ 6642 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6643 of a set of rows of a matrix; using local numbering of rows. 6644 6645 Collective 6646 6647 Input Parameters: 6648 + mat - the matrix 6649 . is - index set of rows to remove 6650 . diag - value put in all diagonals of eliminated rows 6651 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6652 - b - optional vector of right-hand side, that will be adjusted by provided solution 6653 6654 Level: intermediate 6655 6656 Notes: 6657 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6658 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6659 6660 See `MatZeroRows()` for details on how this routine operates. 6661 6662 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6663 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6664 @*/ 6665 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6666 { 6667 PetscInt numRows; 6668 const PetscInt *rows; 6669 6670 PetscFunctionBegin; 6671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6672 PetscValidType(mat, 1); 6673 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6674 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6675 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6676 MatCheckPreallocated(mat, 1); 6677 6678 PetscCall(ISGetLocalSize(is, &numRows)); 6679 PetscCall(ISGetIndices(is, &rows)); 6680 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6681 PetscCall(ISRestoreIndices(is, &rows)); 6682 PetscFunctionReturn(PETSC_SUCCESS); 6683 } 6684 6685 /*@ 6686 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6687 of a set of rows and columns of a matrix; using local numbering of rows. 6688 6689 Collective 6690 6691 Input Parameters: 6692 + mat - the matrix 6693 . numRows - the number of rows to remove 6694 . rows - the global row indices 6695 . diag - value put in all diagonals of eliminated rows 6696 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6697 - b - optional vector of right-hand side, that will be adjusted by provided solution 6698 6699 Level: intermediate 6700 6701 Notes: 6702 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6703 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6704 6705 See `MatZeroRowsColumns()` for details on how this routine operates. 6706 6707 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6708 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6709 @*/ 6710 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6711 { 6712 IS is, newis; 6713 const PetscInt *newRows; 6714 6715 PetscFunctionBegin; 6716 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6717 PetscValidType(mat, 1); 6718 if (numRows) PetscAssertPointer(rows, 3); 6719 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6720 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6721 MatCheckPreallocated(mat, 1); 6722 6723 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6724 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6725 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6726 PetscCall(ISGetIndices(newis, &newRows)); 6727 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6728 PetscCall(ISRestoreIndices(newis, &newRows)); 6729 PetscCall(ISDestroy(&newis)); 6730 PetscCall(ISDestroy(&is)); 6731 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6732 PetscFunctionReturn(PETSC_SUCCESS); 6733 } 6734 6735 /*@ 6736 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6737 of a set of rows and columns of a matrix; using local numbering of rows. 6738 6739 Collective 6740 6741 Input Parameters: 6742 + mat - the matrix 6743 . is - index set of rows to remove 6744 . diag - value put in all diagonals of eliminated rows 6745 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6746 - b - optional vector of right-hand side, that will be adjusted by provided solution 6747 6748 Level: intermediate 6749 6750 Notes: 6751 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6752 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6753 6754 See `MatZeroRowsColumns()` for details on how this routine operates. 6755 6756 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6757 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6758 @*/ 6759 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6760 { 6761 PetscInt numRows; 6762 const PetscInt *rows; 6763 6764 PetscFunctionBegin; 6765 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6766 PetscValidType(mat, 1); 6767 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6768 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6769 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6770 MatCheckPreallocated(mat, 1); 6771 6772 PetscCall(ISGetLocalSize(is, &numRows)); 6773 PetscCall(ISGetIndices(is, &rows)); 6774 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6775 PetscCall(ISRestoreIndices(is, &rows)); 6776 PetscFunctionReturn(PETSC_SUCCESS); 6777 } 6778 6779 /*@ 6780 MatGetSize - Returns the numbers of rows and columns in a matrix. 6781 6782 Not Collective 6783 6784 Input Parameter: 6785 . mat - the matrix 6786 6787 Output Parameters: 6788 + m - the number of global rows 6789 - n - the number of global columns 6790 6791 Level: beginner 6792 6793 Note: 6794 Both output parameters can be `NULL` on input. 6795 6796 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6797 @*/ 6798 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6799 { 6800 PetscFunctionBegin; 6801 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6802 if (m) *m = mat->rmap->N; 6803 if (n) *n = mat->cmap->N; 6804 PetscFunctionReturn(PETSC_SUCCESS); 6805 } 6806 6807 /*@ 6808 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6809 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6810 6811 Not Collective 6812 6813 Input Parameter: 6814 . mat - the matrix 6815 6816 Output Parameters: 6817 + m - the number of local rows, use `NULL` to not obtain this value 6818 - n - the number of local columns, use `NULL` to not obtain this value 6819 6820 Level: beginner 6821 6822 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6823 @*/ 6824 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6825 { 6826 PetscFunctionBegin; 6827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6828 if (m) PetscAssertPointer(m, 2); 6829 if (n) PetscAssertPointer(n, 3); 6830 if (m) *m = mat->rmap->n; 6831 if (n) *n = mat->cmap->n; 6832 PetscFunctionReturn(PETSC_SUCCESS); 6833 } 6834 6835 /*@ 6836 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6837 vector one multiplies this matrix by that are owned by this processor. 6838 6839 Not Collective, unless matrix has not been allocated, then collective 6840 6841 Input Parameter: 6842 . mat - the matrix 6843 6844 Output Parameters: 6845 + m - the global index of the first local column, use `NULL` to not obtain this value 6846 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6847 6848 Level: developer 6849 6850 Notes: 6851 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6852 6853 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6854 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6855 6856 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6857 the local values in the matrix. 6858 6859 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6860 Layouts](sec_matlayout) for details on matrix layouts. 6861 6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6863 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6864 @*/ 6865 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6866 { 6867 PetscFunctionBegin; 6868 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6869 PetscValidType(mat, 1); 6870 if (m) PetscAssertPointer(m, 2); 6871 if (n) PetscAssertPointer(n, 3); 6872 MatCheckPreallocated(mat, 1); 6873 if (m) *m = mat->cmap->rstart; 6874 if (n) *n = mat->cmap->rend; 6875 PetscFunctionReturn(PETSC_SUCCESS); 6876 } 6877 6878 /*@ 6879 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6880 this MPI process. 6881 6882 Not Collective 6883 6884 Input Parameter: 6885 . mat - the matrix 6886 6887 Output Parameters: 6888 + m - the global index of the first local row, use `NULL` to not obtain this value 6889 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6890 6891 Level: beginner 6892 6893 Notes: 6894 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6895 6896 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6897 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6898 6899 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6900 the local values in the matrix. 6901 6902 The high argument is one more than the last element stored locally. 6903 6904 For all matrices it returns the range of matrix rows associated with rows of a vector that 6905 would contain the result of a matrix vector product with this matrix. See [Matrix 6906 Layouts](sec_matlayout) for details on matrix layouts. 6907 6908 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6909 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6910 @*/ 6911 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6912 { 6913 PetscFunctionBegin; 6914 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6915 PetscValidType(mat, 1); 6916 if (m) PetscAssertPointer(m, 2); 6917 if (n) PetscAssertPointer(n, 3); 6918 MatCheckPreallocated(mat, 1); 6919 if (m) *m = mat->rmap->rstart; 6920 if (n) *n = mat->rmap->rend; 6921 PetscFunctionReturn(PETSC_SUCCESS); 6922 } 6923 6924 /*@C 6925 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6926 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6927 6928 Not Collective, unless matrix has not been allocated 6929 6930 Input Parameter: 6931 . mat - the matrix 6932 6933 Output Parameter: 6934 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6935 where `size` is the number of MPI processes used by `mat` 6936 6937 Level: beginner 6938 6939 Notes: 6940 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6941 6942 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6943 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6944 6945 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6946 the local values in the matrix. 6947 6948 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6949 would contain the result of a matrix vector product with this matrix. See [Matrix 6950 Layouts](sec_matlayout) for details on matrix layouts. 6951 6952 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6953 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6954 `DMDAGetGhostCorners()`, `DM` 6955 @*/ 6956 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6957 { 6958 PetscFunctionBegin; 6959 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6960 PetscValidType(mat, 1); 6961 MatCheckPreallocated(mat, 1); 6962 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6963 PetscFunctionReturn(PETSC_SUCCESS); 6964 } 6965 6966 /*@C 6967 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6968 vector one multiplies this vector by that are owned by each processor. 6969 6970 Not Collective, unless matrix has not been allocated 6971 6972 Input Parameter: 6973 . mat - the matrix 6974 6975 Output Parameter: 6976 . ranges - start of each processors portion plus one more than the total length at the end 6977 6978 Level: beginner 6979 6980 Notes: 6981 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6982 6983 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6984 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6985 6986 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6987 the local values in the matrix. 6988 6989 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6990 Layouts](sec_matlayout) for details on matrix layouts. 6991 6992 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6993 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6994 `DMDAGetGhostCorners()`, `DM` 6995 @*/ 6996 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6997 { 6998 PetscFunctionBegin; 6999 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7000 PetscValidType(mat, 1); 7001 MatCheckPreallocated(mat, 1); 7002 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7003 PetscFunctionReturn(PETSC_SUCCESS); 7004 } 7005 7006 /*@ 7007 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7008 7009 Not Collective 7010 7011 Input Parameter: 7012 . A - matrix 7013 7014 Output Parameters: 7015 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7016 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7017 7018 Level: intermediate 7019 7020 Note: 7021 You should call `ISDestroy()` on the returned `IS` 7022 7023 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7024 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7025 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7026 details on matrix layouts. 7027 7028 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7029 @*/ 7030 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7031 { 7032 PetscErrorCode (*f)(Mat, IS *, IS *); 7033 7034 PetscFunctionBegin; 7035 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7036 PetscValidType(A, 1); 7037 MatCheckPreallocated(A, 1); 7038 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7039 if (f) { 7040 PetscCall((*f)(A, rows, cols)); 7041 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7042 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7043 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7044 } 7045 PetscFunctionReturn(PETSC_SUCCESS); 7046 } 7047 7048 /*@ 7049 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7050 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7051 to complete the factorization. 7052 7053 Collective 7054 7055 Input Parameters: 7056 + fact - the factorized matrix obtained with `MatGetFactor()` 7057 . mat - the matrix 7058 . row - row permutation 7059 . col - column permutation 7060 - info - structure containing 7061 .vb 7062 levels - number of levels of fill. 7063 expected fill - as ratio of original fill. 7064 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7065 missing diagonal entries) 7066 .ve 7067 7068 Level: developer 7069 7070 Notes: 7071 See [Matrix Factorization](sec_matfactor) for additional information. 7072 7073 Most users should employ the `KSP` interface for linear solvers 7074 instead of working directly with matrix algebra routines such as this. 7075 See, e.g., `KSPCreate()`. 7076 7077 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7078 7079 Fortran Note: 7080 A valid (non-null) `info` argument must be provided 7081 7082 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7083 `MatGetOrdering()`, `MatFactorInfo` 7084 @*/ 7085 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7086 { 7087 PetscFunctionBegin; 7088 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7089 PetscValidType(mat, 2); 7090 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7091 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7092 PetscAssertPointer(info, 5); 7093 PetscAssertPointer(fact, 1); 7094 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7095 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7096 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7097 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7098 MatCheckPreallocated(mat, 2); 7099 7100 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7101 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7102 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7103 PetscFunctionReturn(PETSC_SUCCESS); 7104 } 7105 7106 /*@ 7107 MatICCFactorSymbolic - Performs symbolic incomplete 7108 Cholesky factorization for a symmetric matrix. Use 7109 `MatCholeskyFactorNumeric()` to complete the factorization. 7110 7111 Collective 7112 7113 Input Parameters: 7114 + fact - the factorized matrix obtained with `MatGetFactor()` 7115 . mat - the matrix to be factored 7116 . perm - row and column permutation 7117 - info - structure containing 7118 .vb 7119 levels - number of levels of fill. 7120 expected fill - as ratio of original fill. 7121 .ve 7122 7123 Level: developer 7124 7125 Notes: 7126 Most users should employ the `KSP` interface for linear solvers 7127 instead of working directly with matrix algebra routines such as this. 7128 See, e.g., `KSPCreate()`. 7129 7130 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7131 7132 Fortran Note: 7133 A valid (non-null) `info` argument must be provided 7134 7135 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7136 @*/ 7137 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7138 { 7139 PetscFunctionBegin; 7140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7141 PetscValidType(mat, 2); 7142 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7143 PetscAssertPointer(info, 4); 7144 PetscAssertPointer(fact, 1); 7145 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7146 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7147 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7149 MatCheckPreallocated(mat, 2); 7150 7151 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7152 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7153 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7154 PetscFunctionReturn(PETSC_SUCCESS); 7155 } 7156 7157 /*@C 7158 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7159 points to an array of valid matrices, they may be reused to store the new 7160 submatrices. 7161 7162 Collective 7163 7164 Input Parameters: 7165 + mat - the matrix 7166 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7167 . irow - index set of rows to extract 7168 . icol - index set of columns to extract 7169 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7170 7171 Output Parameter: 7172 . submat - the array of submatrices 7173 7174 Level: advanced 7175 7176 Notes: 7177 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7178 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7179 to extract a parallel submatrix. 7180 7181 Some matrix types place restrictions on the row and column 7182 indices, such as that they be sorted or that they be equal to each other. 7183 7184 The index sets may not have duplicate entries. 7185 7186 When extracting submatrices from a parallel matrix, each processor can 7187 form a different submatrix by setting the rows and columns of its 7188 individual index sets according to the local submatrix desired. 7189 7190 When finished using the submatrices, the user should destroy 7191 them with `MatDestroySubMatrices()`. 7192 7193 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7194 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7195 7196 This routine creates the matrices in submat; you should NOT create them before 7197 calling it. It also allocates the array of matrix pointers submat. 7198 7199 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7200 request one row/column in a block, they must request all rows/columns that are in 7201 that block. For example, if the block size is 2 you cannot request just row 0 and 7202 column 0. 7203 7204 Fortran Note: 7205 .vb 7206 Mat, pointer :: submat(:) 7207 .ve 7208 7209 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7210 @*/ 7211 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7212 { 7213 PetscInt i; 7214 PetscBool eq; 7215 7216 PetscFunctionBegin; 7217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7218 PetscValidType(mat, 1); 7219 if (n) { 7220 PetscAssertPointer(irow, 3); 7221 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7222 PetscAssertPointer(icol, 4); 7223 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7224 } 7225 PetscAssertPointer(submat, 6); 7226 if (n && scall == MAT_REUSE_MATRIX) { 7227 PetscAssertPointer(*submat, 6); 7228 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7229 } 7230 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7231 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7232 MatCheckPreallocated(mat, 1); 7233 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7234 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7235 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7236 for (i = 0; i < n; i++) { 7237 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7238 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7239 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7240 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7241 if (mat->boundtocpu && mat->bindingpropagates) { 7242 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7243 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7244 } 7245 #endif 7246 } 7247 PetscFunctionReturn(PETSC_SUCCESS); 7248 } 7249 7250 /*@C 7251 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7252 7253 Collective 7254 7255 Input Parameters: 7256 + mat - the matrix 7257 . n - the number of submatrixes to be extracted 7258 . irow - index set of rows to extract 7259 . icol - index set of columns to extract 7260 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7261 7262 Output Parameter: 7263 . submat - the array of submatrices 7264 7265 Level: advanced 7266 7267 Note: 7268 This is used by `PCGASM` 7269 7270 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7271 @*/ 7272 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7273 { 7274 PetscInt i; 7275 PetscBool eq; 7276 7277 PetscFunctionBegin; 7278 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7279 PetscValidType(mat, 1); 7280 if (n) { 7281 PetscAssertPointer(irow, 3); 7282 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7283 PetscAssertPointer(icol, 4); 7284 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7285 } 7286 PetscAssertPointer(submat, 6); 7287 if (n && scall == MAT_REUSE_MATRIX) { 7288 PetscAssertPointer(*submat, 6); 7289 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7290 } 7291 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7292 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7293 MatCheckPreallocated(mat, 1); 7294 7295 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7296 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7297 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7298 for (i = 0; i < n; i++) { 7299 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7300 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7301 } 7302 PetscFunctionReturn(PETSC_SUCCESS); 7303 } 7304 7305 /*@C 7306 MatDestroyMatrices - Destroys an array of matrices 7307 7308 Collective 7309 7310 Input Parameters: 7311 + n - the number of local matrices 7312 - mat - the matrices (this is a pointer to the array of matrices) 7313 7314 Level: advanced 7315 7316 Notes: 7317 Frees not only the matrices, but also the array that contains the matrices 7318 7319 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7320 7321 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7322 @*/ 7323 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7324 { 7325 PetscInt i; 7326 7327 PetscFunctionBegin; 7328 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7329 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7330 PetscAssertPointer(mat, 2); 7331 7332 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7333 7334 /* memory is allocated even if n = 0 */ 7335 PetscCall(PetscFree(*mat)); 7336 PetscFunctionReturn(PETSC_SUCCESS); 7337 } 7338 7339 /*@C 7340 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7341 7342 Collective 7343 7344 Input Parameters: 7345 + n - the number of local matrices 7346 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7347 7348 Level: advanced 7349 7350 Note: 7351 Frees not only the matrices, but also the array that contains the matrices 7352 7353 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7354 @*/ 7355 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7356 { 7357 Mat mat0; 7358 7359 PetscFunctionBegin; 7360 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7361 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7362 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7363 PetscAssertPointer(mat, 2); 7364 7365 mat0 = (*mat)[0]; 7366 if (mat0 && mat0->ops->destroysubmatrices) { 7367 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7368 } else { 7369 PetscCall(MatDestroyMatrices(n, mat)); 7370 } 7371 PetscFunctionReturn(PETSC_SUCCESS); 7372 } 7373 7374 /*@ 7375 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7376 7377 Collective 7378 7379 Input Parameter: 7380 . mat - the matrix 7381 7382 Output Parameter: 7383 . matstruct - the sequential matrix with the nonzero structure of `mat` 7384 7385 Level: developer 7386 7387 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7388 @*/ 7389 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7390 { 7391 PetscFunctionBegin; 7392 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7393 PetscAssertPointer(matstruct, 2); 7394 7395 PetscValidType(mat, 1); 7396 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7397 MatCheckPreallocated(mat, 1); 7398 7399 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7400 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7401 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7402 PetscFunctionReturn(PETSC_SUCCESS); 7403 } 7404 7405 /*@C 7406 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7407 7408 Collective 7409 7410 Input Parameter: 7411 . mat - the matrix 7412 7413 Level: advanced 7414 7415 Note: 7416 This is not needed, one can just call `MatDestroy()` 7417 7418 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7419 @*/ 7420 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7421 { 7422 PetscFunctionBegin; 7423 PetscAssertPointer(mat, 1); 7424 PetscCall(MatDestroy(mat)); 7425 PetscFunctionReturn(PETSC_SUCCESS); 7426 } 7427 7428 /*@ 7429 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7430 replaces the index sets by larger ones that represent submatrices with 7431 additional overlap. 7432 7433 Collective 7434 7435 Input Parameters: 7436 + mat - the matrix 7437 . n - the number of index sets 7438 . is - the array of index sets (these index sets will changed during the call) 7439 - ov - the additional overlap requested 7440 7441 Options Database Key: 7442 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7443 7444 Level: developer 7445 7446 Note: 7447 The computed overlap preserves the matrix block sizes when the blocks are square. 7448 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7449 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7450 7451 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7452 @*/ 7453 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7454 { 7455 PetscInt i, bs, cbs; 7456 7457 PetscFunctionBegin; 7458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7459 PetscValidType(mat, 1); 7460 PetscValidLogicalCollectiveInt(mat, n, 2); 7461 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7462 if (n) { 7463 PetscAssertPointer(is, 3); 7464 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7465 } 7466 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7467 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7468 MatCheckPreallocated(mat, 1); 7469 7470 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7471 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7472 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7473 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7474 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7475 if (bs == cbs) { 7476 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7477 } 7478 PetscFunctionReturn(PETSC_SUCCESS); 7479 } 7480 7481 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7482 7483 /*@ 7484 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7485 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7486 additional overlap. 7487 7488 Collective 7489 7490 Input Parameters: 7491 + mat - the matrix 7492 . n - the number of index sets 7493 . is - the array of index sets (these index sets will changed during the call) 7494 - ov - the additional overlap requested 7495 7496 ` Options Database Key: 7497 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7498 7499 Level: developer 7500 7501 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7502 @*/ 7503 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7504 { 7505 PetscInt i; 7506 7507 PetscFunctionBegin; 7508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7509 PetscValidType(mat, 1); 7510 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7511 if (n) { 7512 PetscAssertPointer(is, 3); 7513 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7514 } 7515 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7516 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7517 MatCheckPreallocated(mat, 1); 7518 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7519 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7520 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7521 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7522 PetscFunctionReturn(PETSC_SUCCESS); 7523 } 7524 7525 /*@ 7526 MatGetBlockSize - Returns the matrix block size. 7527 7528 Not Collective 7529 7530 Input Parameter: 7531 . mat - the matrix 7532 7533 Output Parameter: 7534 . bs - block size 7535 7536 Level: intermediate 7537 7538 Notes: 7539 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7540 7541 If the block size has not been set yet this routine returns 1. 7542 7543 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7544 @*/ 7545 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7546 { 7547 PetscFunctionBegin; 7548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7549 PetscAssertPointer(bs, 2); 7550 *bs = mat->rmap->bs; 7551 PetscFunctionReturn(PETSC_SUCCESS); 7552 } 7553 7554 /*@ 7555 MatGetBlockSizes - Returns the matrix block row and column sizes. 7556 7557 Not Collective 7558 7559 Input Parameter: 7560 . mat - the matrix 7561 7562 Output Parameters: 7563 + rbs - row block size 7564 - cbs - column block size 7565 7566 Level: intermediate 7567 7568 Notes: 7569 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7570 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7571 7572 If a block size has not been set yet this routine returns 1. 7573 7574 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7575 @*/ 7576 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7577 { 7578 PetscFunctionBegin; 7579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7580 if (rbs) PetscAssertPointer(rbs, 2); 7581 if (cbs) PetscAssertPointer(cbs, 3); 7582 if (rbs) *rbs = mat->rmap->bs; 7583 if (cbs) *cbs = mat->cmap->bs; 7584 PetscFunctionReturn(PETSC_SUCCESS); 7585 } 7586 7587 /*@ 7588 MatSetBlockSize - Sets the matrix block size. 7589 7590 Logically Collective 7591 7592 Input Parameters: 7593 + mat - the matrix 7594 - bs - block size 7595 7596 Level: intermediate 7597 7598 Notes: 7599 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7600 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7601 7602 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7603 is compatible with the matrix local sizes. 7604 7605 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7606 @*/ 7607 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7608 { 7609 PetscFunctionBegin; 7610 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7611 PetscValidLogicalCollectiveInt(mat, bs, 2); 7612 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7613 PetscFunctionReturn(PETSC_SUCCESS); 7614 } 7615 7616 typedef struct { 7617 PetscInt n; 7618 IS *is; 7619 Mat *mat; 7620 PetscObjectState nonzerostate; 7621 Mat C; 7622 } EnvelopeData; 7623 7624 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7625 { 7626 EnvelopeData *edata = (EnvelopeData *)*ptr; 7627 7628 PetscFunctionBegin; 7629 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7630 PetscCall(PetscFree(edata->is)); 7631 PetscCall(PetscFree(edata)); 7632 PetscFunctionReturn(PETSC_SUCCESS); 7633 } 7634 7635 /*@ 7636 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7637 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7638 7639 Collective 7640 7641 Input Parameter: 7642 . mat - the matrix 7643 7644 Level: intermediate 7645 7646 Notes: 7647 There can be zeros within the blocks 7648 7649 The blocks can overlap between processes, including laying on more than two processes 7650 7651 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7652 @*/ 7653 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7654 { 7655 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7656 PetscInt *diag, *odiag, sc; 7657 VecScatter scatter; 7658 PetscScalar *seqv; 7659 const PetscScalar *parv; 7660 const PetscInt *ia, *ja; 7661 PetscBool set, flag, done; 7662 Mat AA = mat, A; 7663 MPI_Comm comm; 7664 PetscMPIInt rank, size, tag; 7665 MPI_Status status; 7666 PetscContainer container; 7667 EnvelopeData *edata; 7668 Vec seq, par; 7669 IS isglobal; 7670 7671 PetscFunctionBegin; 7672 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7673 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7674 if (!set || !flag) { 7675 /* TODO: only needs nonzero structure of transpose */ 7676 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7677 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7678 } 7679 PetscCall(MatAIJGetLocalMat(AA, &A)); 7680 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7681 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7682 7683 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7684 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7685 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7686 PetscCallMPI(MPI_Comm_size(comm, &size)); 7687 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7688 7689 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7690 7691 if (rank > 0) { 7692 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7693 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7694 } 7695 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7696 for (i = 0; i < n; i++) { 7697 env = PetscMax(env, ja[ia[i + 1] - 1]); 7698 II = rstart + i; 7699 if (env == II) { 7700 starts[lblocks] = tbs; 7701 sizes[lblocks++] = 1 + II - tbs; 7702 tbs = 1 + II; 7703 } 7704 } 7705 if (rank < size - 1) { 7706 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7707 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7708 } 7709 7710 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7711 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7712 PetscCall(MatDestroy(&A)); 7713 7714 PetscCall(PetscNew(&edata)); 7715 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7716 edata->n = lblocks; 7717 /* create IS needed for extracting blocks from the original matrix */ 7718 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7719 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7720 7721 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7722 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7723 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7724 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7725 PetscCall(MatSetType(edata->C, MATAIJ)); 7726 7727 /* Communicate the start and end of each row, from each block to the correct rank */ 7728 /* TODO: Use PetscSF instead of VecScatter */ 7729 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7730 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7731 PetscCall(VecGetArrayWrite(seq, &seqv)); 7732 for (PetscInt i = 0; i < lblocks; i++) { 7733 for (PetscInt j = 0; j < sizes[i]; j++) { 7734 seqv[cnt] = starts[i]; 7735 seqv[cnt + 1] = starts[i] + sizes[i]; 7736 cnt += 2; 7737 } 7738 } 7739 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7740 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7741 sc -= cnt; 7742 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7743 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7744 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7745 PetscCall(ISDestroy(&isglobal)); 7746 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7747 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7748 PetscCall(VecScatterDestroy(&scatter)); 7749 PetscCall(VecDestroy(&seq)); 7750 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7751 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7752 PetscCall(VecGetArrayRead(par, &parv)); 7753 cnt = 0; 7754 PetscCall(MatGetSize(mat, NULL, &n)); 7755 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7756 PetscInt start, end, d = 0, od = 0; 7757 7758 start = (PetscInt)PetscRealPart(parv[cnt]); 7759 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7760 cnt += 2; 7761 7762 if (start < cstart) { 7763 od += cstart - start + n - cend; 7764 d += cend - cstart; 7765 } else if (start < cend) { 7766 od += n - cend; 7767 d += cend - start; 7768 } else od += n - start; 7769 if (end <= cstart) { 7770 od -= cstart - end + n - cend; 7771 d -= cend - cstart; 7772 } else if (end < cend) { 7773 od -= n - cend; 7774 d -= cend - end; 7775 } else od -= n - end; 7776 7777 odiag[i] = od; 7778 diag[i] = d; 7779 } 7780 PetscCall(VecRestoreArrayRead(par, &parv)); 7781 PetscCall(VecDestroy(&par)); 7782 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7783 PetscCall(PetscFree2(diag, odiag)); 7784 PetscCall(PetscFree2(sizes, starts)); 7785 7786 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7787 PetscCall(PetscContainerSetPointer(container, edata)); 7788 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7789 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7790 PetscCall(PetscObjectDereference((PetscObject)container)); 7791 PetscFunctionReturn(PETSC_SUCCESS); 7792 } 7793 7794 /*@ 7795 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7796 7797 Collective 7798 7799 Input Parameters: 7800 + A - the matrix 7801 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7802 7803 Output Parameter: 7804 . C - matrix with inverted block diagonal of `A` 7805 7806 Level: advanced 7807 7808 Note: 7809 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7810 7811 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7812 @*/ 7813 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7814 { 7815 PetscContainer container; 7816 EnvelopeData *edata; 7817 PetscObjectState nonzerostate; 7818 7819 PetscFunctionBegin; 7820 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7821 if (!container) { 7822 PetscCall(MatComputeVariableBlockEnvelope(A)); 7823 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7824 } 7825 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7826 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7827 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7828 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7829 7830 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7831 *C = edata->C; 7832 7833 for (PetscInt i = 0; i < edata->n; i++) { 7834 Mat D; 7835 PetscScalar *dvalues; 7836 7837 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7838 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7839 PetscCall(MatSeqDenseInvert(D)); 7840 PetscCall(MatDenseGetArray(D, &dvalues)); 7841 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7842 PetscCall(MatDestroy(&D)); 7843 } 7844 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7845 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7846 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7847 PetscFunctionReturn(PETSC_SUCCESS); 7848 } 7849 7850 /*@ 7851 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7852 7853 Not Collective 7854 7855 Input Parameters: 7856 + mat - the matrix 7857 . nblocks - the number of blocks on this process, each block can only exist on a single process 7858 - bsizes - the block sizes 7859 7860 Level: intermediate 7861 7862 Notes: 7863 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7864 7865 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. 7866 7867 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7868 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7869 @*/ 7870 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7871 { 7872 PetscInt ncnt = 0, nlocal; 7873 7874 PetscFunctionBegin; 7875 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7876 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7877 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); 7878 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7879 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); 7880 PetscCall(PetscFree(mat->bsizes)); 7881 mat->nblocks = nblocks; 7882 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7883 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7884 PetscFunctionReturn(PETSC_SUCCESS); 7885 } 7886 7887 /*@C 7888 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7889 7890 Not Collective; No Fortran Support 7891 7892 Input Parameter: 7893 . mat - the matrix 7894 7895 Output Parameters: 7896 + nblocks - the number of blocks on this process 7897 - bsizes - the block sizes 7898 7899 Level: intermediate 7900 7901 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7902 @*/ 7903 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7904 { 7905 PetscFunctionBegin; 7906 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7907 if (nblocks) *nblocks = mat->nblocks; 7908 if (bsizes) *bsizes = mat->bsizes; 7909 PetscFunctionReturn(PETSC_SUCCESS); 7910 } 7911 7912 /*@ 7913 MatSetBlockSizes - Sets the matrix block row and column sizes. 7914 7915 Logically Collective 7916 7917 Input Parameters: 7918 + mat - the matrix 7919 . rbs - row block size 7920 - cbs - column block size 7921 7922 Level: intermediate 7923 7924 Notes: 7925 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7926 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7927 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7928 7929 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7930 are compatible with the matrix local sizes. 7931 7932 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7933 7934 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7935 @*/ 7936 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7937 { 7938 PetscFunctionBegin; 7939 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7940 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7941 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7942 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7943 if (mat->rmap->refcnt) { 7944 ISLocalToGlobalMapping l2g = NULL; 7945 PetscLayout nmap = NULL; 7946 7947 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7948 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7949 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7950 mat->rmap = nmap; 7951 mat->rmap->mapping = l2g; 7952 } 7953 if (mat->cmap->refcnt) { 7954 ISLocalToGlobalMapping l2g = NULL; 7955 PetscLayout nmap = NULL; 7956 7957 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7958 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7959 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7960 mat->cmap = nmap; 7961 mat->cmap->mapping = l2g; 7962 } 7963 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7964 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7965 PetscFunctionReturn(PETSC_SUCCESS); 7966 } 7967 7968 /*@ 7969 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7970 7971 Logically Collective 7972 7973 Input Parameters: 7974 + mat - the matrix 7975 . fromRow - matrix from which to copy row block size 7976 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7977 7978 Level: developer 7979 7980 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 7981 @*/ 7982 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 7983 { 7984 PetscFunctionBegin; 7985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7986 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 7987 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 7988 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 7989 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 7990 PetscFunctionReturn(PETSC_SUCCESS); 7991 } 7992 7993 /*@ 7994 MatResidual - Default routine to calculate the residual r = b - Ax 7995 7996 Collective 7997 7998 Input Parameters: 7999 + mat - the matrix 8000 . b - the right-hand-side 8001 - x - the approximate solution 8002 8003 Output Parameter: 8004 . r - location to store the residual 8005 8006 Level: developer 8007 8008 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8009 @*/ 8010 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8011 { 8012 PetscFunctionBegin; 8013 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8014 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8015 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8016 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8017 PetscValidType(mat, 1); 8018 MatCheckPreallocated(mat, 1); 8019 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8020 if (!mat->ops->residual) { 8021 PetscCall(MatMult(mat, x, r)); 8022 PetscCall(VecAYPX(r, -1.0, b)); 8023 } else { 8024 PetscUseTypeMethod(mat, residual, b, x, r); 8025 } 8026 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8027 PetscFunctionReturn(PETSC_SUCCESS); 8028 } 8029 8030 /*@C 8031 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8032 8033 Collective 8034 8035 Input Parameters: 8036 + mat - the matrix 8037 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8038 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8039 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8040 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8041 always used. 8042 8043 Output Parameters: 8044 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8045 . 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 8046 . ja - the column indices, use `NULL` if not needed 8047 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8048 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8049 8050 Level: developer 8051 8052 Notes: 8053 You CANNOT change any of the ia[] or ja[] values. 8054 8055 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8056 8057 Fortran Notes: 8058 Use 8059 .vb 8060 PetscInt, pointer :: ia(:),ja(:) 8061 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8062 ! Access the ith and jth entries via ia(i) and ja(j) 8063 .ve 8064 8065 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8066 @*/ 8067 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8068 { 8069 PetscFunctionBegin; 8070 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8071 PetscValidType(mat, 1); 8072 if (n) PetscAssertPointer(n, 5); 8073 if (ia) PetscAssertPointer(ia, 6); 8074 if (ja) PetscAssertPointer(ja, 7); 8075 if (done) PetscAssertPointer(done, 8); 8076 MatCheckPreallocated(mat, 1); 8077 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8078 else { 8079 if (done) *done = PETSC_TRUE; 8080 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8081 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8082 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8083 } 8084 PetscFunctionReturn(PETSC_SUCCESS); 8085 } 8086 8087 /*@C 8088 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8089 8090 Collective 8091 8092 Input Parameters: 8093 + mat - the matrix 8094 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8095 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8096 symmetrized 8097 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8098 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8099 always used. 8100 . n - number of columns in the (possibly compressed) matrix 8101 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8102 - ja - the row indices 8103 8104 Output Parameter: 8105 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8106 8107 Level: developer 8108 8109 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8110 @*/ 8111 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8112 { 8113 PetscFunctionBegin; 8114 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8115 PetscValidType(mat, 1); 8116 PetscAssertPointer(n, 5); 8117 if (ia) PetscAssertPointer(ia, 6); 8118 if (ja) PetscAssertPointer(ja, 7); 8119 PetscAssertPointer(done, 8); 8120 MatCheckPreallocated(mat, 1); 8121 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8122 else { 8123 *done = PETSC_TRUE; 8124 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8125 } 8126 PetscFunctionReturn(PETSC_SUCCESS); 8127 } 8128 8129 /*@C 8130 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8131 8132 Collective 8133 8134 Input Parameters: 8135 + mat - the matrix 8136 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8137 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8138 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8139 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8140 always used. 8141 . n - size of (possibly compressed) matrix 8142 . ia - the row pointers 8143 - ja - the column indices 8144 8145 Output Parameter: 8146 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8147 8148 Level: developer 8149 8150 Note: 8151 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8152 us of the array after it has been restored. If you pass `NULL`, it will 8153 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8154 8155 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8156 @*/ 8157 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8158 { 8159 PetscFunctionBegin; 8160 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8161 PetscValidType(mat, 1); 8162 if (ia) PetscAssertPointer(ia, 6); 8163 if (ja) PetscAssertPointer(ja, 7); 8164 if (done) PetscAssertPointer(done, 8); 8165 MatCheckPreallocated(mat, 1); 8166 8167 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8168 else { 8169 if (done) *done = PETSC_TRUE; 8170 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8171 if (n) *n = 0; 8172 if (ia) *ia = NULL; 8173 if (ja) *ja = NULL; 8174 } 8175 PetscFunctionReturn(PETSC_SUCCESS); 8176 } 8177 8178 /*@C 8179 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8180 8181 Collective 8182 8183 Input Parameters: 8184 + mat - the matrix 8185 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8186 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8187 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8188 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8189 always used. 8190 8191 Output Parameters: 8192 + n - size of (possibly compressed) matrix 8193 . ia - the column pointers 8194 . ja - the row indices 8195 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8196 8197 Level: developer 8198 8199 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8200 @*/ 8201 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8202 { 8203 PetscFunctionBegin; 8204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8205 PetscValidType(mat, 1); 8206 if (ia) PetscAssertPointer(ia, 6); 8207 if (ja) PetscAssertPointer(ja, 7); 8208 PetscAssertPointer(done, 8); 8209 MatCheckPreallocated(mat, 1); 8210 8211 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8212 else { 8213 *done = PETSC_TRUE; 8214 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8215 if (n) *n = 0; 8216 if (ia) *ia = NULL; 8217 if (ja) *ja = NULL; 8218 } 8219 PetscFunctionReturn(PETSC_SUCCESS); 8220 } 8221 8222 /*@ 8223 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8224 `MatGetColumnIJ()`. 8225 8226 Collective 8227 8228 Input Parameters: 8229 + mat - the matrix 8230 . ncolors - maximum color value 8231 . n - number of entries in colorarray 8232 - colorarray - array indicating color for each column 8233 8234 Output Parameter: 8235 . iscoloring - coloring generated using colorarray information 8236 8237 Level: developer 8238 8239 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8240 @*/ 8241 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8242 { 8243 PetscFunctionBegin; 8244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8245 PetscValidType(mat, 1); 8246 PetscAssertPointer(colorarray, 4); 8247 PetscAssertPointer(iscoloring, 5); 8248 MatCheckPreallocated(mat, 1); 8249 8250 if (!mat->ops->coloringpatch) { 8251 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8252 } else { 8253 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8254 } 8255 PetscFunctionReturn(PETSC_SUCCESS); 8256 } 8257 8258 /*@ 8259 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8260 8261 Logically Collective 8262 8263 Input Parameter: 8264 . mat - the factored matrix to be reset 8265 8266 Level: developer 8267 8268 Notes: 8269 This routine should be used only with factored matrices formed by in-place 8270 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8271 format). This option can save memory, for example, when solving nonlinear 8272 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8273 ILU(0) preconditioner. 8274 8275 One can specify in-place ILU(0) factorization by calling 8276 .vb 8277 PCType(pc,PCILU); 8278 PCFactorSeUseInPlace(pc); 8279 .ve 8280 or by using the options -pc_type ilu -pc_factor_in_place 8281 8282 In-place factorization ILU(0) can also be used as a local 8283 solver for the blocks within the block Jacobi or additive Schwarz 8284 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8285 for details on setting local solver options. 8286 8287 Most users should employ the `KSP` interface for linear solvers 8288 instead of working directly with matrix algebra routines such as this. 8289 See, e.g., `KSPCreate()`. 8290 8291 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8292 @*/ 8293 PetscErrorCode MatSetUnfactored(Mat mat) 8294 { 8295 PetscFunctionBegin; 8296 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8297 PetscValidType(mat, 1); 8298 MatCheckPreallocated(mat, 1); 8299 mat->factortype = MAT_FACTOR_NONE; 8300 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8301 PetscUseTypeMethod(mat, setunfactored); 8302 PetscFunctionReturn(PETSC_SUCCESS); 8303 } 8304 8305 /*@ 8306 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8307 as the original matrix. 8308 8309 Collective 8310 8311 Input Parameters: 8312 + mat - the original matrix 8313 . isrow - parallel `IS` containing the rows this processor should obtain 8314 . 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. 8315 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8316 8317 Output Parameter: 8318 . newmat - the new submatrix, of the same type as the original matrix 8319 8320 Level: advanced 8321 8322 Notes: 8323 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8324 8325 Some matrix types place restrictions on the row and column indices, such 8326 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; 8327 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8328 8329 The index sets may not have duplicate entries. 8330 8331 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8332 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8333 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8334 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8335 you are finished using it. 8336 8337 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8338 the input matrix. 8339 8340 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8341 8342 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8343 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8344 8345 Example usage: 8346 Consider the following 8x8 matrix with 34 non-zero values, that is 8347 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8348 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8349 as follows 8350 .vb 8351 1 2 0 | 0 3 0 | 0 4 8352 Proc0 0 5 6 | 7 0 0 | 8 0 8353 9 0 10 | 11 0 0 | 12 0 8354 ------------------------------------- 8355 13 0 14 | 15 16 17 | 0 0 8356 Proc1 0 18 0 | 19 20 21 | 0 0 8357 0 0 0 | 22 23 0 | 24 0 8358 ------------------------------------- 8359 Proc2 25 26 27 | 0 0 28 | 29 0 8360 30 0 0 | 31 32 33 | 0 34 8361 .ve 8362 8363 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8364 8365 .vb 8366 2 0 | 0 3 0 | 0 8367 Proc0 5 6 | 7 0 0 | 8 8368 ------------------------------- 8369 Proc1 18 0 | 19 20 21 | 0 8370 ------------------------------- 8371 Proc2 26 27 | 0 0 28 | 29 8372 0 0 | 31 32 33 | 0 8373 .ve 8374 8375 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8376 @*/ 8377 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8378 { 8379 PetscMPIInt size; 8380 Mat *local; 8381 IS iscoltmp; 8382 PetscBool flg; 8383 8384 PetscFunctionBegin; 8385 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8386 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8387 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8388 PetscAssertPointer(newmat, 5); 8389 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8390 PetscValidType(mat, 1); 8391 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8392 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8393 8394 MatCheckPreallocated(mat, 1); 8395 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8396 8397 if (!iscol || isrow == iscol) { 8398 PetscBool stride; 8399 PetscMPIInt grabentirematrix = 0, grab; 8400 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8401 if (stride) { 8402 PetscInt first, step, n, rstart, rend; 8403 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8404 if (step == 1) { 8405 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8406 if (rstart == first) { 8407 PetscCall(ISGetLocalSize(isrow, &n)); 8408 if (n == rend - rstart) grabentirematrix = 1; 8409 } 8410 } 8411 } 8412 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8413 if (grab) { 8414 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8415 if (cll == MAT_INITIAL_MATRIX) { 8416 *newmat = mat; 8417 PetscCall(PetscObjectReference((PetscObject)mat)); 8418 } 8419 PetscFunctionReturn(PETSC_SUCCESS); 8420 } 8421 } 8422 8423 if (!iscol) { 8424 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8425 } else { 8426 iscoltmp = iscol; 8427 } 8428 8429 /* if original matrix is on just one processor then use submatrix generated */ 8430 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8431 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8432 goto setproperties; 8433 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8434 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8435 *newmat = *local; 8436 PetscCall(PetscFree(local)); 8437 goto setproperties; 8438 } else if (!mat->ops->createsubmatrix) { 8439 /* Create a new matrix type that implements the operation using the full matrix */ 8440 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8441 switch (cll) { 8442 case MAT_INITIAL_MATRIX: 8443 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8444 break; 8445 case MAT_REUSE_MATRIX: 8446 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8447 break; 8448 default: 8449 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8450 } 8451 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8452 goto setproperties; 8453 } 8454 8455 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8456 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8457 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8458 8459 setproperties: 8460 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8461 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8462 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8463 } 8464 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8465 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8466 PetscFunctionReturn(PETSC_SUCCESS); 8467 } 8468 8469 /*@ 8470 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8471 8472 Not Collective 8473 8474 Input Parameters: 8475 + A - the matrix we wish to propagate options from 8476 - B - the matrix we wish to propagate options to 8477 8478 Level: beginner 8479 8480 Note: 8481 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8482 8483 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8484 @*/ 8485 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8486 { 8487 PetscFunctionBegin; 8488 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8489 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8490 B->symmetry_eternal = A->symmetry_eternal; 8491 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8492 B->symmetric = A->symmetric; 8493 B->structurally_symmetric = A->structurally_symmetric; 8494 B->spd = A->spd; 8495 B->hermitian = A->hermitian; 8496 PetscFunctionReturn(PETSC_SUCCESS); 8497 } 8498 8499 /*@ 8500 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8501 used during the assembly process to store values that belong to 8502 other processors. 8503 8504 Not Collective 8505 8506 Input Parameters: 8507 + mat - the matrix 8508 . size - the initial size of the stash. 8509 - bsize - the initial size of the block-stash(if used). 8510 8511 Options Database Keys: 8512 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8513 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8514 8515 Level: intermediate 8516 8517 Notes: 8518 The block-stash is used for values set with `MatSetValuesBlocked()` while 8519 the stash is used for values set with `MatSetValues()` 8520 8521 Run with the option -info and look for output of the form 8522 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8523 to determine the appropriate value, MM, to use for size and 8524 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8525 to determine the value, BMM to use for bsize 8526 8527 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8528 @*/ 8529 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8530 { 8531 PetscFunctionBegin; 8532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8533 PetscValidType(mat, 1); 8534 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8535 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8536 PetscFunctionReturn(PETSC_SUCCESS); 8537 } 8538 8539 /*@ 8540 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8541 the matrix 8542 8543 Neighbor-wise Collective 8544 8545 Input Parameters: 8546 + A - the matrix 8547 . x - the vector to be multiplied by the interpolation operator 8548 - y - the vector to be added to the result 8549 8550 Output Parameter: 8551 . w - the resulting vector 8552 8553 Level: intermediate 8554 8555 Notes: 8556 `w` may be the same vector as `y`. 8557 8558 This allows one to use either the restriction or interpolation (its transpose) 8559 matrix to do the interpolation 8560 8561 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8562 @*/ 8563 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8564 { 8565 PetscInt M, N, Ny; 8566 8567 PetscFunctionBegin; 8568 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8569 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8570 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8571 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8572 PetscCall(MatGetSize(A, &M, &N)); 8573 PetscCall(VecGetSize(y, &Ny)); 8574 if (M == Ny) { 8575 PetscCall(MatMultAdd(A, x, y, w)); 8576 } else { 8577 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8578 } 8579 PetscFunctionReturn(PETSC_SUCCESS); 8580 } 8581 8582 /*@ 8583 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8584 the matrix 8585 8586 Neighbor-wise Collective 8587 8588 Input Parameters: 8589 + A - the matrix 8590 - x - the vector to be interpolated 8591 8592 Output Parameter: 8593 . y - the resulting vector 8594 8595 Level: intermediate 8596 8597 Note: 8598 This allows one to use either the restriction or interpolation (its transpose) 8599 matrix to do the interpolation 8600 8601 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8602 @*/ 8603 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8604 { 8605 PetscInt M, N, Ny; 8606 8607 PetscFunctionBegin; 8608 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8609 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8610 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8611 PetscCall(MatGetSize(A, &M, &N)); 8612 PetscCall(VecGetSize(y, &Ny)); 8613 if (M == Ny) { 8614 PetscCall(MatMult(A, x, y)); 8615 } else { 8616 PetscCall(MatMultTranspose(A, x, y)); 8617 } 8618 PetscFunctionReturn(PETSC_SUCCESS); 8619 } 8620 8621 /*@ 8622 MatRestrict - $y = A*x$ or $A^T*x$ 8623 8624 Neighbor-wise Collective 8625 8626 Input Parameters: 8627 + A - the matrix 8628 - x - the vector to be restricted 8629 8630 Output Parameter: 8631 . y - the resulting vector 8632 8633 Level: intermediate 8634 8635 Note: 8636 This allows one to use either the restriction or interpolation (its transpose) 8637 matrix to do the restriction 8638 8639 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8640 @*/ 8641 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8642 { 8643 PetscInt M, N, Nx; 8644 8645 PetscFunctionBegin; 8646 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8647 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8648 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8649 PetscCall(MatGetSize(A, &M, &N)); 8650 PetscCall(VecGetSize(x, &Nx)); 8651 if (M == Nx) { 8652 PetscCall(MatMultTranspose(A, x, y)); 8653 } else { 8654 PetscCall(MatMult(A, x, y)); 8655 } 8656 PetscFunctionReturn(PETSC_SUCCESS); 8657 } 8658 8659 /*@ 8660 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8661 8662 Neighbor-wise Collective 8663 8664 Input Parameters: 8665 + A - the matrix 8666 . x - the input dense matrix to be multiplied 8667 - w - the input dense matrix to be added to the result 8668 8669 Output Parameter: 8670 . y - the output dense matrix 8671 8672 Level: intermediate 8673 8674 Note: 8675 This allows one to use either the restriction or interpolation (its transpose) 8676 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8677 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8678 8679 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8680 @*/ 8681 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8682 { 8683 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8684 PetscBool trans = PETSC_TRUE; 8685 MatReuse reuse = MAT_INITIAL_MATRIX; 8686 8687 PetscFunctionBegin; 8688 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8689 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8690 PetscValidType(x, 2); 8691 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8692 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8693 PetscCall(MatGetSize(A, &M, &N)); 8694 PetscCall(MatGetSize(x, &Mx, &Nx)); 8695 if (N == Mx) trans = PETSC_FALSE; 8696 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); 8697 Mo = trans ? N : M; 8698 if (*y) { 8699 PetscCall(MatGetSize(*y, &My, &Ny)); 8700 if (Mo == My && Nx == Ny) { 8701 reuse = MAT_REUSE_MATRIX; 8702 } else { 8703 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); 8704 PetscCall(MatDestroy(y)); 8705 } 8706 } 8707 8708 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8709 PetscBool flg; 8710 8711 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8712 if (w) { 8713 PetscInt My, Ny, Mw, Nw; 8714 8715 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8716 PetscCall(MatGetSize(*y, &My, &Ny)); 8717 PetscCall(MatGetSize(w, &Mw, &Nw)); 8718 if (!flg || My != Mw || Ny != Nw) w = NULL; 8719 } 8720 if (!w) { 8721 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8722 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8723 PetscCall(PetscObjectDereference((PetscObject)w)); 8724 } else { 8725 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8726 } 8727 } 8728 if (!trans) { 8729 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8730 } else { 8731 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8732 } 8733 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8734 PetscFunctionReturn(PETSC_SUCCESS); 8735 } 8736 8737 /*@ 8738 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8739 8740 Neighbor-wise Collective 8741 8742 Input Parameters: 8743 + A - the matrix 8744 - x - the input dense matrix 8745 8746 Output Parameter: 8747 . y - the output dense matrix 8748 8749 Level: intermediate 8750 8751 Note: 8752 This allows one to use either the restriction or interpolation (its transpose) 8753 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8754 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8755 8756 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8757 @*/ 8758 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8759 { 8760 PetscFunctionBegin; 8761 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8762 PetscFunctionReturn(PETSC_SUCCESS); 8763 } 8764 8765 /*@ 8766 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8767 8768 Neighbor-wise Collective 8769 8770 Input Parameters: 8771 + A - the matrix 8772 - x - the input dense matrix 8773 8774 Output Parameter: 8775 . y - the output dense matrix 8776 8777 Level: intermediate 8778 8779 Note: 8780 This allows one to use either the restriction or interpolation (its transpose) 8781 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8782 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8783 8784 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8785 @*/ 8786 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8787 { 8788 PetscFunctionBegin; 8789 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8790 PetscFunctionReturn(PETSC_SUCCESS); 8791 } 8792 8793 /*@ 8794 MatGetNullSpace - retrieves the null space of a matrix. 8795 8796 Logically Collective 8797 8798 Input Parameters: 8799 + mat - the matrix 8800 - nullsp - the null space object 8801 8802 Level: developer 8803 8804 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8805 @*/ 8806 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8807 { 8808 PetscFunctionBegin; 8809 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8810 PetscAssertPointer(nullsp, 2); 8811 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8812 PetscFunctionReturn(PETSC_SUCCESS); 8813 } 8814 8815 /*@C 8816 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8817 8818 Logically Collective 8819 8820 Input Parameters: 8821 + n - the number of matrices 8822 - mat - the array of matrices 8823 8824 Output Parameters: 8825 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8826 8827 Level: developer 8828 8829 Note: 8830 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8831 8832 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8833 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8834 @*/ 8835 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8836 { 8837 PetscFunctionBegin; 8838 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8839 PetscAssertPointer(mat, 2); 8840 PetscAssertPointer(nullsp, 3); 8841 8842 PetscCall(PetscCalloc1(3 * n, nullsp)); 8843 for (PetscInt i = 0; i < n; i++) { 8844 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8845 (*nullsp)[i] = mat[i]->nullsp; 8846 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8847 (*nullsp)[n + i] = mat[i]->nearnullsp; 8848 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8849 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8850 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8851 } 8852 PetscFunctionReturn(PETSC_SUCCESS); 8853 } 8854 8855 /*@C 8856 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8857 8858 Logically Collective 8859 8860 Input Parameters: 8861 + n - the number of matrices 8862 . mat - the array of matrices 8863 - nullsp - an array of null spaces 8864 8865 Level: developer 8866 8867 Note: 8868 Call `MatGetNullSpaces()` to create `nullsp` 8869 8870 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8871 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8872 @*/ 8873 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8874 { 8875 PetscFunctionBegin; 8876 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8877 PetscAssertPointer(mat, 2); 8878 PetscAssertPointer(nullsp, 3); 8879 PetscAssertPointer(*nullsp, 3); 8880 8881 for (PetscInt i = 0; i < n; i++) { 8882 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8883 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8884 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8885 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8886 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8887 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8888 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8889 } 8890 PetscCall(PetscFree(*nullsp)); 8891 PetscFunctionReturn(PETSC_SUCCESS); 8892 } 8893 8894 /*@ 8895 MatSetNullSpace - attaches a null space to a matrix. 8896 8897 Logically Collective 8898 8899 Input Parameters: 8900 + mat - the matrix 8901 - nullsp - the null space object 8902 8903 Level: advanced 8904 8905 Notes: 8906 This null space is used by the `KSP` linear solvers to solve singular systems. 8907 8908 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` 8909 8910 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 8911 to zero but the linear system will still be solved in a least squares sense. 8912 8913 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8914 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)$, plus the range of $A^T$, $R(A^T)$. 8915 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 8916 $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 8917 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)$. 8918 This $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8919 8920 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called 8921 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8922 routine also automatically calls `MatSetTransposeNullSpace()`. 8923 8924 The user should call `MatNullSpaceDestroy()`. 8925 8926 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8927 `KSPSetPCSide()` 8928 @*/ 8929 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8930 { 8931 PetscFunctionBegin; 8932 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8933 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8934 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8935 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8936 mat->nullsp = nullsp; 8937 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8938 PetscFunctionReturn(PETSC_SUCCESS); 8939 } 8940 8941 /*@ 8942 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8943 8944 Logically Collective 8945 8946 Input Parameters: 8947 + mat - the matrix 8948 - nullsp - the null space object 8949 8950 Level: developer 8951 8952 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8953 @*/ 8954 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8955 { 8956 PetscFunctionBegin; 8957 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8958 PetscValidType(mat, 1); 8959 PetscAssertPointer(nullsp, 2); 8960 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8961 PetscFunctionReturn(PETSC_SUCCESS); 8962 } 8963 8964 /*@ 8965 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8966 8967 Logically Collective 8968 8969 Input Parameters: 8970 + mat - the matrix 8971 - nullsp - the null space object 8972 8973 Level: advanced 8974 8975 Notes: 8976 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8977 8978 See `MatSetNullSpace()` 8979 8980 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 8981 @*/ 8982 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 8983 { 8984 PetscFunctionBegin; 8985 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8986 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8987 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8988 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 8989 mat->transnullsp = nullsp; 8990 PetscFunctionReturn(PETSC_SUCCESS); 8991 } 8992 8993 /*@ 8994 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 8995 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 8996 8997 Logically Collective 8998 8999 Input Parameters: 9000 + mat - the matrix 9001 - nullsp - the null space object 9002 9003 Level: advanced 9004 9005 Notes: 9006 Overwrites any previous near null space that may have been attached 9007 9008 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9009 9010 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9011 @*/ 9012 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9013 { 9014 PetscFunctionBegin; 9015 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9016 PetscValidType(mat, 1); 9017 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9018 MatCheckPreallocated(mat, 1); 9019 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9020 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9021 mat->nearnullsp = nullsp; 9022 PetscFunctionReturn(PETSC_SUCCESS); 9023 } 9024 9025 /*@ 9026 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9027 9028 Not Collective 9029 9030 Input Parameter: 9031 . mat - the matrix 9032 9033 Output Parameter: 9034 . nullsp - the null space object, `NULL` if not set 9035 9036 Level: advanced 9037 9038 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9039 @*/ 9040 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9041 { 9042 PetscFunctionBegin; 9043 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9044 PetscValidType(mat, 1); 9045 PetscAssertPointer(nullsp, 2); 9046 MatCheckPreallocated(mat, 1); 9047 *nullsp = mat->nearnullsp; 9048 PetscFunctionReturn(PETSC_SUCCESS); 9049 } 9050 9051 /*@ 9052 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9053 9054 Collective 9055 9056 Input Parameters: 9057 + mat - the matrix 9058 . row - row/column permutation 9059 - info - information on desired factorization process 9060 9061 Level: developer 9062 9063 Notes: 9064 Probably really in-place only when level of fill is zero, otherwise allocates 9065 new space to store factored matrix and deletes previous memory. 9066 9067 Most users should employ the `KSP` interface for linear solvers 9068 instead of working directly with matrix algebra routines such as this. 9069 See, e.g., `KSPCreate()`. 9070 9071 Fortran Note: 9072 A valid (non-null) `info` argument must be provided 9073 9074 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9075 @*/ 9076 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9077 { 9078 PetscFunctionBegin; 9079 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9080 PetscValidType(mat, 1); 9081 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9082 PetscAssertPointer(info, 3); 9083 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9084 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9085 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9086 MatCheckPreallocated(mat, 1); 9087 PetscUseTypeMethod(mat, iccfactor, row, info); 9088 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9089 PetscFunctionReturn(PETSC_SUCCESS); 9090 } 9091 9092 /*@ 9093 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9094 ghosted ones. 9095 9096 Not Collective 9097 9098 Input Parameters: 9099 + mat - the matrix 9100 - diag - the diagonal values, including ghost ones 9101 9102 Level: developer 9103 9104 Notes: 9105 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9106 9107 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9108 9109 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9110 @*/ 9111 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9112 { 9113 PetscMPIInt size; 9114 9115 PetscFunctionBegin; 9116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9117 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9118 PetscValidType(mat, 1); 9119 9120 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9121 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9122 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9123 if (size == 1) { 9124 PetscInt n, m; 9125 PetscCall(VecGetSize(diag, &n)); 9126 PetscCall(MatGetSize(mat, NULL, &m)); 9127 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9128 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9129 } else { 9130 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9131 } 9132 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9133 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9134 PetscFunctionReturn(PETSC_SUCCESS); 9135 } 9136 9137 /*@ 9138 MatGetInertia - Gets the inertia from a factored matrix 9139 9140 Collective 9141 9142 Input Parameter: 9143 . mat - the matrix 9144 9145 Output Parameters: 9146 + nneg - number of negative eigenvalues 9147 . nzero - number of zero eigenvalues 9148 - npos - number of positive eigenvalues 9149 9150 Level: advanced 9151 9152 Note: 9153 Matrix must have been factored by `MatCholeskyFactor()` 9154 9155 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9156 @*/ 9157 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9158 { 9159 PetscFunctionBegin; 9160 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9161 PetscValidType(mat, 1); 9162 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9163 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9164 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9165 PetscFunctionReturn(PETSC_SUCCESS); 9166 } 9167 9168 /*@C 9169 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9170 9171 Neighbor-wise Collective 9172 9173 Input Parameters: 9174 + mat - the factored matrix obtained with `MatGetFactor()` 9175 - b - the right-hand-side vectors 9176 9177 Output Parameter: 9178 . x - the result vectors 9179 9180 Level: developer 9181 9182 Note: 9183 The vectors `b` and `x` cannot be the same. I.e., one cannot 9184 call `MatSolves`(A,x,x). 9185 9186 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9187 @*/ 9188 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9189 { 9190 PetscFunctionBegin; 9191 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9192 PetscValidType(mat, 1); 9193 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9194 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9195 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9196 9197 MatCheckPreallocated(mat, 1); 9198 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9199 PetscUseTypeMethod(mat, solves, b, x); 9200 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9201 PetscFunctionReturn(PETSC_SUCCESS); 9202 } 9203 9204 /*@ 9205 MatIsSymmetric - Test whether a matrix is symmetric 9206 9207 Collective 9208 9209 Input Parameters: 9210 + A - the matrix to test 9211 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9212 9213 Output Parameter: 9214 . flg - the result 9215 9216 Level: intermediate 9217 9218 Notes: 9219 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9220 9221 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9222 9223 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9224 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9225 9226 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9227 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9228 @*/ 9229 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9230 { 9231 PetscFunctionBegin; 9232 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9233 PetscAssertPointer(flg, 3); 9234 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9235 else { 9236 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9237 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9238 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9239 } 9240 PetscFunctionReturn(PETSC_SUCCESS); 9241 } 9242 9243 /*@ 9244 MatIsHermitian - Test whether a matrix is Hermitian 9245 9246 Collective 9247 9248 Input Parameters: 9249 + A - the matrix to test 9250 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9251 9252 Output Parameter: 9253 . flg - the result 9254 9255 Level: intermediate 9256 9257 Notes: 9258 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9259 9260 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9261 9262 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9263 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9264 9265 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9266 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9267 @*/ 9268 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9269 { 9270 PetscFunctionBegin; 9271 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9272 PetscAssertPointer(flg, 3); 9273 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9274 else { 9275 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9276 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9277 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9278 } 9279 PetscFunctionReturn(PETSC_SUCCESS); 9280 } 9281 9282 /*@ 9283 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9284 9285 Not Collective 9286 9287 Input Parameter: 9288 . A - the matrix to check 9289 9290 Output Parameters: 9291 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9292 - flg - the result (only valid if set is `PETSC_TRUE`) 9293 9294 Level: advanced 9295 9296 Notes: 9297 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9298 if you want it explicitly checked 9299 9300 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9301 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9302 9303 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9304 @*/ 9305 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9306 { 9307 PetscFunctionBegin; 9308 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9309 PetscAssertPointer(set, 2); 9310 PetscAssertPointer(flg, 3); 9311 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9312 *set = PETSC_TRUE; 9313 *flg = PetscBool3ToBool(A->symmetric); 9314 } else { 9315 *set = PETSC_FALSE; 9316 } 9317 PetscFunctionReturn(PETSC_SUCCESS); 9318 } 9319 9320 /*@ 9321 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9322 9323 Not Collective 9324 9325 Input Parameter: 9326 . A - the matrix to check 9327 9328 Output Parameters: 9329 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9330 - flg - the result (only valid if set is `PETSC_TRUE`) 9331 9332 Level: advanced 9333 9334 Notes: 9335 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9336 9337 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9338 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9339 9340 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9341 @*/ 9342 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9343 { 9344 PetscFunctionBegin; 9345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9346 PetscAssertPointer(set, 2); 9347 PetscAssertPointer(flg, 3); 9348 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9349 *set = PETSC_TRUE; 9350 *flg = PetscBool3ToBool(A->spd); 9351 } else { 9352 *set = PETSC_FALSE; 9353 } 9354 PetscFunctionReturn(PETSC_SUCCESS); 9355 } 9356 9357 /*@ 9358 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9359 9360 Not Collective 9361 9362 Input Parameter: 9363 . A - the matrix to check 9364 9365 Output Parameters: 9366 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9367 - flg - the result (only valid if set is `PETSC_TRUE`) 9368 9369 Level: advanced 9370 9371 Notes: 9372 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9373 if you want it explicitly checked 9374 9375 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9376 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9377 9378 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9379 @*/ 9380 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9381 { 9382 PetscFunctionBegin; 9383 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9384 PetscAssertPointer(set, 2); 9385 PetscAssertPointer(flg, 3); 9386 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9387 *set = PETSC_TRUE; 9388 *flg = PetscBool3ToBool(A->hermitian); 9389 } else { 9390 *set = PETSC_FALSE; 9391 } 9392 PetscFunctionReturn(PETSC_SUCCESS); 9393 } 9394 9395 /*@ 9396 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9397 9398 Collective 9399 9400 Input Parameter: 9401 . A - the matrix to test 9402 9403 Output Parameter: 9404 . flg - the result 9405 9406 Level: intermediate 9407 9408 Notes: 9409 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9410 9411 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 9412 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9413 9414 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9415 @*/ 9416 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9417 { 9418 PetscFunctionBegin; 9419 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9420 PetscAssertPointer(flg, 2); 9421 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9422 *flg = PetscBool3ToBool(A->structurally_symmetric); 9423 } else { 9424 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9425 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9426 } 9427 PetscFunctionReturn(PETSC_SUCCESS); 9428 } 9429 9430 /*@ 9431 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9432 9433 Not Collective 9434 9435 Input Parameter: 9436 . A - the matrix to check 9437 9438 Output Parameters: 9439 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9440 - flg - the result (only valid if set is PETSC_TRUE) 9441 9442 Level: advanced 9443 9444 Notes: 9445 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 9446 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9447 9448 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9449 9450 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9451 @*/ 9452 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9453 { 9454 PetscFunctionBegin; 9455 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9456 PetscAssertPointer(set, 2); 9457 PetscAssertPointer(flg, 3); 9458 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9459 *set = PETSC_TRUE; 9460 *flg = PetscBool3ToBool(A->structurally_symmetric); 9461 } else { 9462 *set = PETSC_FALSE; 9463 } 9464 PetscFunctionReturn(PETSC_SUCCESS); 9465 } 9466 9467 /*@ 9468 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9469 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9470 9471 Not Collective 9472 9473 Input Parameter: 9474 . mat - the matrix 9475 9476 Output Parameters: 9477 + nstash - the size of the stash 9478 . reallocs - the number of additional mallocs incurred. 9479 . bnstash - the size of the block stash 9480 - breallocs - the number of additional mallocs incurred.in the block stash 9481 9482 Level: advanced 9483 9484 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9485 @*/ 9486 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9487 { 9488 PetscFunctionBegin; 9489 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9490 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9491 PetscFunctionReturn(PETSC_SUCCESS); 9492 } 9493 9494 /*@ 9495 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9496 parallel layout, `PetscLayout` for rows and columns 9497 9498 Collective 9499 9500 Input Parameter: 9501 . mat - the matrix 9502 9503 Output Parameters: 9504 + right - (optional) vector that the matrix can be multiplied against 9505 - left - (optional) vector that the matrix vector product can be stored in 9506 9507 Level: advanced 9508 9509 Notes: 9510 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()`. 9511 9512 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9513 9514 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9515 @*/ 9516 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9517 { 9518 PetscFunctionBegin; 9519 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9520 PetscValidType(mat, 1); 9521 if (mat->ops->getvecs) { 9522 PetscUseTypeMethod(mat, getvecs, right, left); 9523 } else { 9524 if (right) { 9525 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9526 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9527 PetscCall(VecSetType(*right, mat->defaultvectype)); 9528 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9529 if (mat->boundtocpu && mat->bindingpropagates) { 9530 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9531 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9532 } 9533 #endif 9534 } 9535 if (left) { 9536 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9537 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9538 PetscCall(VecSetType(*left, mat->defaultvectype)); 9539 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9540 if (mat->boundtocpu && mat->bindingpropagates) { 9541 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9542 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9543 } 9544 #endif 9545 } 9546 } 9547 PetscFunctionReturn(PETSC_SUCCESS); 9548 } 9549 9550 /*@ 9551 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9552 with default values. 9553 9554 Not Collective 9555 9556 Input Parameter: 9557 . info - the `MatFactorInfo` data structure 9558 9559 Level: developer 9560 9561 Notes: 9562 The solvers are generally used through the `KSP` and `PC` objects, for example 9563 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9564 9565 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9566 9567 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9568 @*/ 9569 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9570 { 9571 PetscFunctionBegin; 9572 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9573 PetscFunctionReturn(PETSC_SUCCESS); 9574 } 9575 9576 /*@ 9577 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9578 9579 Collective 9580 9581 Input Parameters: 9582 + mat - the factored matrix 9583 - is - the index set defining the Schur indices (0-based) 9584 9585 Level: advanced 9586 9587 Notes: 9588 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9589 9590 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9591 9592 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9593 9594 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9595 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9596 @*/ 9597 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9598 { 9599 PetscErrorCode (*f)(Mat, IS); 9600 9601 PetscFunctionBegin; 9602 PetscValidType(mat, 1); 9603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9604 PetscValidType(is, 2); 9605 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9606 PetscCheckSameComm(mat, 1, is, 2); 9607 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9608 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9609 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9610 PetscCall(MatDestroy(&mat->schur)); 9611 PetscCall((*f)(mat, is)); 9612 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9613 PetscFunctionReturn(PETSC_SUCCESS); 9614 } 9615 9616 /*@ 9617 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9618 9619 Logically Collective 9620 9621 Input Parameters: 9622 + F - the factored matrix obtained by calling `MatGetFactor()` 9623 . S - location where to return the Schur complement, can be `NULL` 9624 - status - the status of the Schur complement matrix, can be `NULL` 9625 9626 Level: advanced 9627 9628 Notes: 9629 You must call `MatFactorSetSchurIS()` before calling this routine. 9630 9631 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9632 9633 The routine provides a copy of the Schur matrix stored within the solver data structures. 9634 The caller must destroy the object when it is no longer needed. 9635 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9636 9637 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) 9638 9639 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9640 9641 Developer Note: 9642 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9643 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9644 9645 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9646 @*/ 9647 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9648 { 9649 PetscFunctionBegin; 9650 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9651 if (S) PetscAssertPointer(S, 2); 9652 if (status) PetscAssertPointer(status, 3); 9653 if (S) { 9654 PetscErrorCode (*f)(Mat, Mat *); 9655 9656 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9657 if (f) { 9658 PetscCall((*f)(F, S)); 9659 } else { 9660 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9661 } 9662 } 9663 if (status) *status = F->schur_status; 9664 PetscFunctionReturn(PETSC_SUCCESS); 9665 } 9666 9667 /*@ 9668 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9669 9670 Logically Collective 9671 9672 Input Parameters: 9673 + F - the factored matrix obtained by calling `MatGetFactor()` 9674 . S - location where to return the Schur complement, can be `NULL` 9675 - status - the status of the Schur complement matrix, can be `NULL` 9676 9677 Level: advanced 9678 9679 Notes: 9680 You must call `MatFactorSetSchurIS()` before calling this routine. 9681 9682 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9683 9684 The routine returns a the Schur Complement stored within the data structures of the solver. 9685 9686 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9687 9688 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9689 9690 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9691 9692 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9693 9694 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9695 @*/ 9696 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9697 { 9698 PetscFunctionBegin; 9699 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9700 if (S) { 9701 PetscAssertPointer(S, 2); 9702 *S = F->schur; 9703 } 9704 if (status) { 9705 PetscAssertPointer(status, 3); 9706 *status = F->schur_status; 9707 } 9708 PetscFunctionReturn(PETSC_SUCCESS); 9709 } 9710 9711 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9712 { 9713 Mat S = F->schur; 9714 9715 PetscFunctionBegin; 9716 switch (F->schur_status) { 9717 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9718 case MAT_FACTOR_SCHUR_INVERTED: 9719 if (S) { 9720 S->ops->solve = NULL; 9721 S->ops->matsolve = NULL; 9722 S->ops->solvetranspose = NULL; 9723 S->ops->matsolvetranspose = NULL; 9724 S->ops->solveadd = NULL; 9725 S->ops->solvetransposeadd = NULL; 9726 S->factortype = MAT_FACTOR_NONE; 9727 PetscCall(PetscFree(S->solvertype)); 9728 } 9729 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9730 break; 9731 default: 9732 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9733 } 9734 PetscFunctionReturn(PETSC_SUCCESS); 9735 } 9736 9737 /*@ 9738 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9739 9740 Logically Collective 9741 9742 Input Parameters: 9743 + F - the factored matrix obtained by calling `MatGetFactor()` 9744 . S - location where the Schur complement is stored 9745 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9746 9747 Level: advanced 9748 9749 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9750 @*/ 9751 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9752 { 9753 PetscFunctionBegin; 9754 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9755 if (S) { 9756 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9757 *S = NULL; 9758 } 9759 F->schur_status = status; 9760 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9761 PetscFunctionReturn(PETSC_SUCCESS); 9762 } 9763 9764 /*@ 9765 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9766 9767 Logically Collective 9768 9769 Input Parameters: 9770 + F - the factored matrix obtained by calling `MatGetFactor()` 9771 . rhs - location where the right-hand side of the Schur complement system is stored 9772 - sol - location where the solution of the Schur complement system has to be returned 9773 9774 Level: advanced 9775 9776 Notes: 9777 The sizes of the vectors should match the size of the Schur complement 9778 9779 Must be called after `MatFactorSetSchurIS()` 9780 9781 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9782 @*/ 9783 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9784 { 9785 PetscFunctionBegin; 9786 PetscValidType(F, 1); 9787 PetscValidType(rhs, 2); 9788 PetscValidType(sol, 3); 9789 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9790 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9791 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9792 PetscCheckSameComm(F, 1, rhs, 2); 9793 PetscCheckSameComm(F, 1, sol, 3); 9794 PetscCall(MatFactorFactorizeSchurComplement(F)); 9795 switch (F->schur_status) { 9796 case MAT_FACTOR_SCHUR_FACTORED: 9797 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9798 break; 9799 case MAT_FACTOR_SCHUR_INVERTED: 9800 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9801 break; 9802 default: 9803 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9804 } 9805 PetscFunctionReturn(PETSC_SUCCESS); 9806 } 9807 9808 /*@ 9809 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9810 9811 Logically Collective 9812 9813 Input Parameters: 9814 + F - the factored matrix obtained by calling `MatGetFactor()` 9815 . rhs - location where the right-hand side of the Schur complement system is stored 9816 - sol - location where the solution of the Schur complement system has to be returned 9817 9818 Level: advanced 9819 9820 Notes: 9821 The sizes of the vectors should match the size of the Schur complement 9822 9823 Must be called after `MatFactorSetSchurIS()` 9824 9825 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9826 @*/ 9827 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9828 { 9829 PetscFunctionBegin; 9830 PetscValidType(F, 1); 9831 PetscValidType(rhs, 2); 9832 PetscValidType(sol, 3); 9833 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9834 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9835 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9836 PetscCheckSameComm(F, 1, rhs, 2); 9837 PetscCheckSameComm(F, 1, sol, 3); 9838 PetscCall(MatFactorFactorizeSchurComplement(F)); 9839 switch (F->schur_status) { 9840 case MAT_FACTOR_SCHUR_FACTORED: 9841 PetscCall(MatSolve(F->schur, rhs, sol)); 9842 break; 9843 case MAT_FACTOR_SCHUR_INVERTED: 9844 PetscCall(MatMult(F->schur, rhs, sol)); 9845 break; 9846 default: 9847 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9848 } 9849 PetscFunctionReturn(PETSC_SUCCESS); 9850 } 9851 9852 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9853 #if PetscDefined(HAVE_CUDA) 9854 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9855 #endif 9856 9857 /* Schur status updated in the interface */ 9858 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9859 { 9860 Mat S = F->schur; 9861 9862 PetscFunctionBegin; 9863 if (S) { 9864 PetscMPIInt size; 9865 PetscBool isdense, isdensecuda; 9866 9867 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9868 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9869 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9870 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9871 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9872 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9873 if (isdense) { 9874 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9875 } else if (isdensecuda) { 9876 #if defined(PETSC_HAVE_CUDA) 9877 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9878 #endif 9879 } 9880 // HIP?????????????? 9881 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9882 } 9883 PetscFunctionReturn(PETSC_SUCCESS); 9884 } 9885 9886 /*@ 9887 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9888 9889 Logically Collective 9890 9891 Input Parameter: 9892 . F - the factored matrix obtained by calling `MatGetFactor()` 9893 9894 Level: advanced 9895 9896 Notes: 9897 Must be called after `MatFactorSetSchurIS()`. 9898 9899 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9900 9901 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9902 @*/ 9903 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9904 { 9905 PetscFunctionBegin; 9906 PetscValidType(F, 1); 9907 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9908 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9909 PetscCall(MatFactorFactorizeSchurComplement(F)); 9910 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9911 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9912 PetscFunctionReturn(PETSC_SUCCESS); 9913 } 9914 9915 /*@ 9916 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9917 9918 Logically Collective 9919 9920 Input Parameter: 9921 . F - the factored matrix obtained by calling `MatGetFactor()` 9922 9923 Level: advanced 9924 9925 Note: 9926 Must be called after `MatFactorSetSchurIS()` 9927 9928 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9929 @*/ 9930 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9931 { 9932 MatFactorInfo info; 9933 9934 PetscFunctionBegin; 9935 PetscValidType(F, 1); 9936 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9937 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9938 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9939 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9940 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9941 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9942 } else { 9943 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9944 } 9945 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9946 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9947 PetscFunctionReturn(PETSC_SUCCESS); 9948 } 9949 9950 /*@ 9951 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9952 9953 Neighbor-wise Collective 9954 9955 Input Parameters: 9956 + A - the matrix 9957 . P - the projection matrix 9958 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9959 - 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 9960 if the result is a dense matrix this is irrelevant 9961 9962 Output Parameter: 9963 . C - the product matrix 9964 9965 Level: intermediate 9966 9967 Notes: 9968 C will be created and must be destroyed by the user with `MatDestroy()`. 9969 9970 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9971 9972 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 9973 9974 Developer Note: 9975 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9976 9977 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 9978 @*/ 9979 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 9980 { 9981 PetscFunctionBegin; 9982 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 9983 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 9984 9985 if (scall == MAT_INITIAL_MATRIX) { 9986 PetscCall(MatProductCreate(A, P, NULL, C)); 9987 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 9988 PetscCall(MatProductSetAlgorithm(*C, "default")); 9989 PetscCall(MatProductSetFill(*C, fill)); 9990 9991 (*C)->product->api_user = PETSC_TRUE; 9992 PetscCall(MatProductSetFromOptions(*C)); 9993 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); 9994 PetscCall(MatProductSymbolic(*C)); 9995 } else { /* scall == MAT_REUSE_MATRIX */ 9996 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 9997 } 9998 9999 PetscCall(MatProductNumeric(*C)); 10000 (*C)->symmetric = A->symmetric; 10001 (*C)->spd = A->spd; 10002 PetscFunctionReturn(PETSC_SUCCESS); 10003 } 10004 10005 /*@ 10006 MatRARt - Creates the matrix product $C = R * A * R^T$ 10007 10008 Neighbor-wise Collective 10009 10010 Input Parameters: 10011 + A - the matrix 10012 . R - the projection matrix 10013 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10014 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10015 if the result is a dense matrix this is irrelevant 10016 10017 Output Parameter: 10018 . C - the product matrix 10019 10020 Level: intermediate 10021 10022 Notes: 10023 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10024 10025 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10026 10027 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10028 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10029 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10030 We recommend using `MatPtAP()` when possible. 10031 10032 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10033 10034 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10035 @*/ 10036 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10037 { 10038 PetscFunctionBegin; 10039 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10040 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10041 10042 if (scall == MAT_INITIAL_MATRIX) { 10043 PetscCall(MatProductCreate(A, R, NULL, C)); 10044 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10045 PetscCall(MatProductSetAlgorithm(*C, "default")); 10046 PetscCall(MatProductSetFill(*C, fill)); 10047 10048 (*C)->product->api_user = PETSC_TRUE; 10049 PetscCall(MatProductSetFromOptions(*C)); 10050 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); 10051 PetscCall(MatProductSymbolic(*C)); 10052 } else { /* scall == MAT_REUSE_MATRIX */ 10053 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10054 } 10055 10056 PetscCall(MatProductNumeric(*C)); 10057 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10058 PetscFunctionReturn(PETSC_SUCCESS); 10059 } 10060 10061 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10062 { 10063 PetscBool flg = PETSC_TRUE; 10064 10065 PetscFunctionBegin; 10066 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10067 if (scall == MAT_INITIAL_MATRIX) { 10068 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10069 PetscCall(MatProductCreate(A, B, NULL, C)); 10070 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10071 PetscCall(MatProductSetFill(*C, fill)); 10072 } else { /* scall == MAT_REUSE_MATRIX */ 10073 Mat_Product *product = (*C)->product; 10074 10075 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10076 if (flg && product && product->type != ptype) { 10077 PetscCall(MatProductClear(*C)); 10078 product = NULL; 10079 } 10080 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10081 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10082 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10083 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10084 product = (*C)->product; 10085 product->fill = fill; 10086 product->clear = PETSC_TRUE; 10087 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10088 flg = PETSC_FALSE; 10089 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10090 } 10091 } 10092 if (flg) { 10093 (*C)->product->api_user = PETSC_TRUE; 10094 PetscCall(MatProductSetType(*C, ptype)); 10095 PetscCall(MatProductSetFromOptions(*C)); 10096 PetscCall(MatProductSymbolic(*C)); 10097 } 10098 PetscCall(MatProductNumeric(*C)); 10099 PetscFunctionReturn(PETSC_SUCCESS); 10100 } 10101 10102 /*@ 10103 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10104 10105 Neighbor-wise Collective 10106 10107 Input Parameters: 10108 + A - the left matrix 10109 . B - the right matrix 10110 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10111 - 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 10112 if the result is a dense matrix this is irrelevant 10113 10114 Output Parameter: 10115 . C - the product matrix 10116 10117 Notes: 10118 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10119 10120 `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 10121 call to this function with `MAT_INITIAL_MATRIX`. 10122 10123 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10124 10125 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`, 10126 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10127 10128 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10129 10130 Example of Usage: 10131 .vb 10132 MatProductCreate(A,B,NULL,&C); 10133 MatProductSetType(C,MATPRODUCT_AB); 10134 MatProductSymbolic(C); 10135 MatProductNumeric(C); // compute C=A * B 10136 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10137 MatProductNumeric(C); 10138 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10139 MatProductNumeric(C); 10140 .ve 10141 10142 Level: intermediate 10143 10144 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10145 @*/ 10146 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10147 { 10148 PetscFunctionBegin; 10149 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10150 PetscFunctionReturn(PETSC_SUCCESS); 10151 } 10152 10153 /*@ 10154 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10155 10156 Neighbor-wise Collective 10157 10158 Input Parameters: 10159 + A - the left matrix 10160 . B - the right matrix 10161 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10162 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10163 10164 Output Parameter: 10165 . C - the product matrix 10166 10167 Options Database Key: 10168 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10169 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10170 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10171 10172 Level: intermediate 10173 10174 Notes: 10175 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10176 10177 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10178 10179 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10180 actually needed. 10181 10182 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10183 and for pairs of `MATMPIDENSE` matrices. 10184 10185 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10186 10187 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10188 10189 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10190 @*/ 10191 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10192 { 10193 PetscFunctionBegin; 10194 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10195 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10196 PetscFunctionReturn(PETSC_SUCCESS); 10197 } 10198 10199 /*@ 10200 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10201 10202 Neighbor-wise Collective 10203 10204 Input Parameters: 10205 + A - the left matrix 10206 . B - the right matrix 10207 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10208 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10209 10210 Output Parameter: 10211 . C - the product matrix 10212 10213 Level: intermediate 10214 10215 Notes: 10216 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10217 10218 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10219 10220 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10221 10222 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10223 actually needed. 10224 10225 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10226 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10227 10228 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10229 10230 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10231 @*/ 10232 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10233 { 10234 PetscFunctionBegin; 10235 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10236 PetscFunctionReturn(PETSC_SUCCESS); 10237 } 10238 10239 /*@ 10240 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10241 10242 Neighbor-wise Collective 10243 10244 Input Parameters: 10245 + A - the left matrix 10246 . B - the middle matrix 10247 . C - the right matrix 10248 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10249 - 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 10250 if the result is a dense matrix this is irrelevant 10251 10252 Output Parameter: 10253 . D - the product matrix 10254 10255 Level: intermediate 10256 10257 Notes: 10258 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10259 10260 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10261 10262 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10263 10264 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10265 actually needed. 10266 10267 If you have many matrices with the same non-zero structure to multiply, you 10268 should use `MAT_REUSE_MATRIX` in all calls but the first 10269 10270 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10271 10272 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10273 @*/ 10274 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10275 { 10276 PetscFunctionBegin; 10277 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10278 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10279 10280 if (scall == MAT_INITIAL_MATRIX) { 10281 PetscCall(MatProductCreate(A, B, C, D)); 10282 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10283 PetscCall(MatProductSetAlgorithm(*D, "default")); 10284 PetscCall(MatProductSetFill(*D, fill)); 10285 10286 (*D)->product->api_user = PETSC_TRUE; 10287 PetscCall(MatProductSetFromOptions(*D)); 10288 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, 10289 ((PetscObject)C)->type_name); 10290 PetscCall(MatProductSymbolic(*D)); 10291 } else { /* user may change input matrices when REUSE */ 10292 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10293 } 10294 PetscCall(MatProductNumeric(*D)); 10295 PetscFunctionReturn(PETSC_SUCCESS); 10296 } 10297 10298 /*@ 10299 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10300 10301 Collective 10302 10303 Input Parameters: 10304 + mat - the matrix 10305 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10306 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10307 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10308 10309 Output Parameter: 10310 . matredundant - redundant matrix 10311 10312 Level: advanced 10313 10314 Notes: 10315 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10316 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10317 10318 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10319 calling it. 10320 10321 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10322 10323 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10324 @*/ 10325 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10326 { 10327 MPI_Comm comm; 10328 PetscMPIInt size; 10329 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10330 Mat_Redundant *redund = NULL; 10331 PetscSubcomm psubcomm = NULL; 10332 MPI_Comm subcomm_in = subcomm; 10333 Mat *matseq; 10334 IS isrow, iscol; 10335 PetscBool newsubcomm = PETSC_FALSE; 10336 10337 PetscFunctionBegin; 10338 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10339 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10340 PetscAssertPointer(*matredundant, 5); 10341 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10342 } 10343 10344 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10345 if (size == 1 || nsubcomm == 1) { 10346 if (reuse == MAT_INITIAL_MATRIX) { 10347 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10348 } else { 10349 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"); 10350 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10351 } 10352 PetscFunctionReturn(PETSC_SUCCESS); 10353 } 10354 10355 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10356 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10357 MatCheckPreallocated(mat, 1); 10358 10359 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10360 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10361 /* create psubcomm, then get subcomm */ 10362 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10363 PetscCallMPI(MPI_Comm_size(comm, &size)); 10364 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10365 10366 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10367 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10368 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10369 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10370 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10371 newsubcomm = PETSC_TRUE; 10372 PetscCall(PetscSubcommDestroy(&psubcomm)); 10373 } 10374 10375 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10376 if (reuse == MAT_INITIAL_MATRIX) { 10377 mloc_sub = PETSC_DECIDE; 10378 nloc_sub = PETSC_DECIDE; 10379 if (bs < 1) { 10380 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10381 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10382 } else { 10383 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10384 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10385 } 10386 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10387 rstart = rend - mloc_sub; 10388 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10389 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10390 PetscCall(ISSetIdentity(iscol)); 10391 } else { /* reuse == MAT_REUSE_MATRIX */ 10392 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"); 10393 /* retrieve subcomm */ 10394 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10395 redund = (*matredundant)->redundant; 10396 isrow = redund->isrow; 10397 iscol = redund->iscol; 10398 matseq = redund->matseq; 10399 } 10400 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10401 10402 /* get matredundant over subcomm */ 10403 if (reuse == MAT_INITIAL_MATRIX) { 10404 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10405 10406 /* create a supporting struct and attach it to C for reuse */ 10407 PetscCall(PetscNew(&redund)); 10408 (*matredundant)->redundant = redund; 10409 redund->isrow = isrow; 10410 redund->iscol = iscol; 10411 redund->matseq = matseq; 10412 if (newsubcomm) { 10413 redund->subcomm = subcomm; 10414 } else { 10415 redund->subcomm = MPI_COMM_NULL; 10416 } 10417 } else { 10418 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10419 } 10420 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10421 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10422 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10423 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10424 } 10425 #endif 10426 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10427 PetscFunctionReturn(PETSC_SUCCESS); 10428 } 10429 10430 /*@C 10431 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10432 a given `Mat`. Each submatrix can span multiple procs. 10433 10434 Collective 10435 10436 Input Parameters: 10437 + mat - the matrix 10438 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10439 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10440 10441 Output Parameter: 10442 . subMat - parallel sub-matrices each spanning a given `subcomm` 10443 10444 Level: advanced 10445 10446 Notes: 10447 The submatrix partition across processors is dictated by `subComm` a 10448 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10449 is not restricted to be grouped with consecutive original MPI processes. 10450 10451 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10452 map directly to the layout of the original matrix [wrt the local 10453 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10454 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10455 the `subMat`. However the offDiagMat looses some columns - and this is 10456 reconstructed with `MatSetValues()` 10457 10458 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10459 10460 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10461 @*/ 10462 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10463 { 10464 PetscMPIInt commsize, subCommSize; 10465 10466 PetscFunctionBegin; 10467 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10468 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10469 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10470 10471 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"); 10472 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10473 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10474 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10475 PetscFunctionReturn(PETSC_SUCCESS); 10476 } 10477 10478 /*@ 10479 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10480 10481 Not Collective 10482 10483 Input Parameters: 10484 + mat - matrix to extract local submatrix from 10485 . isrow - local row indices for submatrix 10486 - iscol - local column indices for submatrix 10487 10488 Output Parameter: 10489 . submat - the submatrix 10490 10491 Level: intermediate 10492 10493 Notes: 10494 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10495 10496 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10497 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10498 10499 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10500 `MatSetValuesBlockedLocal()` will also be implemented. 10501 10502 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10503 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10504 10505 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10506 @*/ 10507 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10508 { 10509 PetscFunctionBegin; 10510 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10511 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10512 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10513 PetscCheckSameComm(isrow, 2, iscol, 3); 10514 PetscAssertPointer(submat, 4); 10515 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10516 10517 if (mat->ops->getlocalsubmatrix) { 10518 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10519 } else { 10520 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10521 } 10522 PetscFunctionReturn(PETSC_SUCCESS); 10523 } 10524 10525 /*@ 10526 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10527 10528 Not Collective 10529 10530 Input Parameters: 10531 + mat - matrix to extract local submatrix from 10532 . isrow - local row indices for submatrix 10533 . iscol - local column indices for submatrix 10534 - submat - the submatrix 10535 10536 Level: intermediate 10537 10538 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10539 @*/ 10540 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10541 { 10542 PetscFunctionBegin; 10543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10544 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10545 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10546 PetscCheckSameComm(isrow, 2, iscol, 3); 10547 PetscAssertPointer(submat, 4); 10548 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10549 10550 if (mat->ops->restorelocalsubmatrix) { 10551 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10552 } else { 10553 PetscCall(MatDestroy(submat)); 10554 } 10555 *submat = NULL; 10556 PetscFunctionReturn(PETSC_SUCCESS); 10557 } 10558 10559 /*@ 10560 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10561 10562 Collective 10563 10564 Input Parameter: 10565 . mat - the matrix 10566 10567 Output Parameter: 10568 . is - if any rows have zero diagonals this contains the list of them 10569 10570 Level: developer 10571 10572 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10573 @*/ 10574 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10575 { 10576 PetscFunctionBegin; 10577 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10578 PetscValidType(mat, 1); 10579 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10580 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10581 10582 if (!mat->ops->findzerodiagonals) { 10583 Vec diag; 10584 const PetscScalar *a; 10585 PetscInt *rows; 10586 PetscInt rStart, rEnd, r, nrow = 0; 10587 10588 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10589 PetscCall(MatGetDiagonal(mat, diag)); 10590 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10591 PetscCall(VecGetArrayRead(diag, &a)); 10592 for (r = 0; r < rEnd - rStart; ++r) 10593 if (a[r] == 0.0) ++nrow; 10594 PetscCall(PetscMalloc1(nrow, &rows)); 10595 nrow = 0; 10596 for (r = 0; r < rEnd - rStart; ++r) 10597 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10598 PetscCall(VecRestoreArrayRead(diag, &a)); 10599 PetscCall(VecDestroy(&diag)); 10600 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10601 } else { 10602 PetscUseTypeMethod(mat, findzerodiagonals, is); 10603 } 10604 PetscFunctionReturn(PETSC_SUCCESS); 10605 } 10606 10607 /*@ 10608 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10609 10610 Collective 10611 10612 Input Parameter: 10613 . mat - the matrix 10614 10615 Output Parameter: 10616 . is - contains the list of rows with off block diagonal entries 10617 10618 Level: developer 10619 10620 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10621 @*/ 10622 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10623 { 10624 PetscFunctionBegin; 10625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10626 PetscValidType(mat, 1); 10627 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10628 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10629 10630 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10631 PetscFunctionReturn(PETSC_SUCCESS); 10632 } 10633 10634 /*@C 10635 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10636 10637 Collective; No Fortran Support 10638 10639 Input Parameter: 10640 . mat - the matrix 10641 10642 Output Parameter: 10643 . values - the block inverses in column major order (FORTRAN-like) 10644 10645 Level: advanced 10646 10647 Notes: 10648 The size of the blocks is determined by the block size of the matrix. 10649 10650 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10651 10652 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10653 10654 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10655 @*/ 10656 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10657 { 10658 PetscFunctionBegin; 10659 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10660 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10661 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10662 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10663 PetscFunctionReturn(PETSC_SUCCESS); 10664 } 10665 10666 /*@ 10667 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10668 10669 Collective; No Fortran Support 10670 10671 Input Parameters: 10672 + mat - the matrix 10673 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10674 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10675 10676 Output Parameter: 10677 . values - the block inverses in column major order (FORTRAN-like) 10678 10679 Level: advanced 10680 10681 Notes: 10682 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10683 10684 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10685 10686 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10687 @*/ 10688 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10689 { 10690 PetscFunctionBegin; 10691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10692 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10693 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10694 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10695 PetscFunctionReturn(PETSC_SUCCESS); 10696 } 10697 10698 /*@ 10699 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10700 10701 Collective 10702 10703 Input Parameters: 10704 + A - the matrix 10705 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10706 10707 Level: advanced 10708 10709 Note: 10710 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10711 10712 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10713 @*/ 10714 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10715 { 10716 const PetscScalar *vals; 10717 PetscInt *dnnz; 10718 PetscInt m, rstart, rend, bs, i, j; 10719 10720 PetscFunctionBegin; 10721 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10722 PetscCall(MatGetBlockSize(A, &bs)); 10723 PetscCall(MatGetLocalSize(A, &m, NULL)); 10724 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10725 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10726 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10727 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10728 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10729 PetscCall(PetscFree(dnnz)); 10730 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10731 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10732 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10733 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10734 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10735 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10736 PetscFunctionReturn(PETSC_SUCCESS); 10737 } 10738 10739 /*@ 10740 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10741 via `MatTransposeColoringCreate()`. 10742 10743 Collective 10744 10745 Input Parameter: 10746 . c - coloring context 10747 10748 Level: intermediate 10749 10750 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10751 @*/ 10752 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10753 { 10754 MatTransposeColoring matcolor = *c; 10755 10756 PetscFunctionBegin; 10757 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10758 if (--((PetscObject)matcolor)->refct > 0) { 10759 matcolor = NULL; 10760 PetscFunctionReturn(PETSC_SUCCESS); 10761 } 10762 10763 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10764 PetscCall(PetscFree(matcolor->rows)); 10765 PetscCall(PetscFree(matcolor->den2sp)); 10766 PetscCall(PetscFree(matcolor->colorforcol)); 10767 PetscCall(PetscFree(matcolor->columns)); 10768 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10769 PetscCall(PetscHeaderDestroy(c)); 10770 PetscFunctionReturn(PETSC_SUCCESS); 10771 } 10772 10773 /*@ 10774 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10775 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10776 `MatTransposeColoring` to sparse `B`. 10777 10778 Collective 10779 10780 Input Parameters: 10781 + coloring - coloring context created with `MatTransposeColoringCreate()` 10782 - B - sparse matrix 10783 10784 Output Parameter: 10785 . Btdense - dense matrix $B^T$ 10786 10787 Level: developer 10788 10789 Note: 10790 These are used internally for some implementations of `MatRARt()` 10791 10792 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10793 @*/ 10794 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10795 { 10796 PetscFunctionBegin; 10797 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10798 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10799 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10800 10801 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10802 PetscFunctionReturn(PETSC_SUCCESS); 10803 } 10804 10805 /*@ 10806 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10807 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10808 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10809 $C_{sp}$ from $C_{den}$. 10810 10811 Collective 10812 10813 Input Parameters: 10814 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10815 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10816 10817 Output Parameter: 10818 . Csp - sparse matrix 10819 10820 Level: developer 10821 10822 Note: 10823 These are used internally for some implementations of `MatRARt()` 10824 10825 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10826 @*/ 10827 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10828 { 10829 PetscFunctionBegin; 10830 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10831 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10832 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10833 10834 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10835 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10836 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10837 PetscFunctionReturn(PETSC_SUCCESS); 10838 } 10839 10840 /*@ 10841 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10842 10843 Collective 10844 10845 Input Parameters: 10846 + mat - the matrix product C 10847 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10848 10849 Output Parameter: 10850 . color - the new coloring context 10851 10852 Level: intermediate 10853 10854 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10855 `MatTransColoringApplyDenToSp()` 10856 @*/ 10857 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10858 { 10859 MatTransposeColoring c; 10860 MPI_Comm comm; 10861 10862 PetscFunctionBegin; 10863 PetscAssertPointer(color, 3); 10864 10865 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10866 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10867 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10868 c->ctype = iscoloring->ctype; 10869 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10870 *color = c; 10871 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10872 PetscFunctionReturn(PETSC_SUCCESS); 10873 } 10874 10875 /*@ 10876 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10877 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10878 10879 Not Collective 10880 10881 Input Parameter: 10882 . mat - the matrix 10883 10884 Output Parameter: 10885 . state - the current state 10886 10887 Level: intermediate 10888 10889 Notes: 10890 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10891 different matrices 10892 10893 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10894 10895 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10896 10897 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10898 @*/ 10899 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10900 { 10901 PetscFunctionBegin; 10902 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10903 *state = mat->nonzerostate; 10904 PetscFunctionReturn(PETSC_SUCCESS); 10905 } 10906 10907 /*@ 10908 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10909 matrices from each processor 10910 10911 Collective 10912 10913 Input Parameters: 10914 + comm - the communicators the parallel matrix will live on 10915 . seqmat - the input sequential matrices 10916 . n - number of local columns (or `PETSC_DECIDE`) 10917 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10918 10919 Output Parameter: 10920 . mpimat - the parallel matrix generated 10921 10922 Level: developer 10923 10924 Note: 10925 The number of columns of the matrix in EACH processor MUST be the same. 10926 10927 .seealso: [](ch_matrices), `Mat` 10928 @*/ 10929 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10930 { 10931 PetscMPIInt size; 10932 10933 PetscFunctionBegin; 10934 PetscCallMPI(MPI_Comm_size(comm, &size)); 10935 if (size == 1) { 10936 if (reuse == MAT_INITIAL_MATRIX) { 10937 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10938 } else { 10939 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10940 } 10941 PetscFunctionReturn(PETSC_SUCCESS); 10942 } 10943 10944 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"); 10945 10946 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10947 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10948 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10949 PetscFunctionReturn(PETSC_SUCCESS); 10950 } 10951 10952 /*@ 10953 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10954 10955 Collective 10956 10957 Input Parameters: 10958 + A - the matrix to create subdomains from 10959 - N - requested number of subdomains 10960 10961 Output Parameters: 10962 + n - number of subdomains resulting on this MPI process 10963 - iss - `IS` list with indices of subdomains on this MPI process 10964 10965 Level: advanced 10966 10967 Note: 10968 The number of subdomains must be smaller than the communicator size 10969 10970 .seealso: [](ch_matrices), `Mat`, `IS` 10971 @*/ 10972 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10973 { 10974 MPI_Comm comm, subcomm; 10975 PetscMPIInt size, rank, color; 10976 PetscInt rstart, rend, k; 10977 10978 PetscFunctionBegin; 10979 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 10980 PetscCallMPI(MPI_Comm_size(comm, &size)); 10981 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 10982 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); 10983 *n = 1; 10984 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 10985 color = rank / k; 10986 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 10987 PetscCall(PetscMalloc1(1, iss)); 10988 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 10989 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 10990 PetscCallMPI(MPI_Comm_free(&subcomm)); 10991 PetscFunctionReturn(PETSC_SUCCESS); 10992 } 10993 10994 /*@ 10995 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 10996 10997 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 10998 If they are not the same, uses `MatMatMatMult()`. 10999 11000 Once the coarse grid problem is constructed, correct for interpolation operators 11001 that are not of full rank, which can legitimately happen in the case of non-nested 11002 geometric multigrid. 11003 11004 Input Parameters: 11005 + restrct - restriction operator 11006 . dA - fine grid matrix 11007 . interpolate - interpolation operator 11008 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11009 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11010 11011 Output Parameter: 11012 . A - the Galerkin coarse matrix 11013 11014 Options Database Key: 11015 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11016 11017 Level: developer 11018 11019 Note: 11020 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11021 11022 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11023 @*/ 11024 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11025 { 11026 IS zerorows; 11027 Vec diag; 11028 11029 PetscFunctionBegin; 11030 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11031 /* Construct the coarse grid matrix */ 11032 if (interpolate == restrct) { 11033 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11034 } else { 11035 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11036 } 11037 11038 /* If the interpolation matrix is not of full rank, A will have zero rows. 11039 This can legitimately happen in the case of non-nested geometric multigrid. 11040 In that event, we set the rows of the matrix to the rows of the identity, 11041 ignoring the equations (as the RHS will also be zero). */ 11042 11043 PetscCall(MatFindZeroRows(*A, &zerorows)); 11044 11045 if (zerorows != NULL) { /* if there are any zero rows */ 11046 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11047 PetscCall(MatGetDiagonal(*A, diag)); 11048 PetscCall(VecISSet(diag, zerorows, 1.0)); 11049 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11050 PetscCall(VecDestroy(&diag)); 11051 PetscCall(ISDestroy(&zerorows)); 11052 } 11053 PetscFunctionReturn(PETSC_SUCCESS); 11054 } 11055 11056 /*@C 11057 MatSetOperation - Allows user to set a matrix operation for any matrix type 11058 11059 Logically Collective 11060 11061 Input Parameters: 11062 + mat - the matrix 11063 . op - the name of the operation 11064 - f - the function that provides the operation 11065 11066 Level: developer 11067 11068 Example Usage: 11069 .vb 11070 extern PetscErrorCode usermult(Mat, Vec, Vec); 11071 11072 PetscCall(MatCreateXXX(comm, ..., &A)); 11073 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11074 .ve 11075 11076 Notes: 11077 See the file `include/petscmat.h` for a complete list of matrix 11078 operations, which all have the form MATOP_<OPERATION>, where 11079 <OPERATION> is the name (in all capital letters) of the 11080 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11081 11082 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11083 sequence as the usual matrix interface routines, since they 11084 are intended to be accessed via the usual matrix interface 11085 routines, e.g., 11086 .vb 11087 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11088 .ve 11089 11090 In particular each function MUST return `PETSC_SUCCESS` on success and 11091 nonzero on failure. 11092 11093 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11094 11095 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11096 @*/ 11097 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11098 { 11099 PetscFunctionBegin; 11100 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11101 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11102 (((void (**)(void))mat->ops)[op]) = f; 11103 PetscFunctionReturn(PETSC_SUCCESS); 11104 } 11105 11106 /*@C 11107 MatGetOperation - Gets a matrix operation for any matrix type. 11108 11109 Not Collective 11110 11111 Input Parameters: 11112 + mat - the matrix 11113 - op - the name of the operation 11114 11115 Output Parameter: 11116 . f - the function that provides the operation 11117 11118 Level: developer 11119 11120 Example Usage: 11121 .vb 11122 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11123 11124 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11125 .ve 11126 11127 Notes: 11128 See the file include/petscmat.h for a complete list of matrix 11129 operations, which all have the form MATOP_<OPERATION>, where 11130 <OPERATION> is the name (in all capital letters) of the 11131 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11132 11133 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11134 11135 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11136 @*/ 11137 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11138 { 11139 PetscFunctionBegin; 11140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11141 *f = (((void (**)(void))mat->ops)[op]); 11142 PetscFunctionReturn(PETSC_SUCCESS); 11143 } 11144 11145 /*@ 11146 MatHasOperation - Determines whether the given matrix supports the particular operation. 11147 11148 Not Collective 11149 11150 Input Parameters: 11151 + mat - the matrix 11152 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11153 11154 Output Parameter: 11155 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11156 11157 Level: advanced 11158 11159 Note: 11160 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11161 11162 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11163 @*/ 11164 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11165 { 11166 PetscFunctionBegin; 11167 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11168 PetscAssertPointer(has, 3); 11169 if (mat->ops->hasoperation) { 11170 PetscUseTypeMethod(mat, hasoperation, op, has); 11171 } else { 11172 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11173 else { 11174 *has = PETSC_FALSE; 11175 if (op == MATOP_CREATE_SUBMATRIX) { 11176 PetscMPIInt size; 11177 11178 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11179 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11180 } 11181 } 11182 } 11183 PetscFunctionReturn(PETSC_SUCCESS); 11184 } 11185 11186 /*@ 11187 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11188 11189 Collective 11190 11191 Input Parameter: 11192 . mat - the matrix 11193 11194 Output Parameter: 11195 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11196 11197 Level: beginner 11198 11199 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11200 @*/ 11201 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11202 { 11203 PetscFunctionBegin; 11204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11205 PetscValidType(mat, 1); 11206 PetscAssertPointer(cong, 2); 11207 if (!mat->rmap || !mat->cmap) { 11208 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11209 PetscFunctionReturn(PETSC_SUCCESS); 11210 } 11211 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11212 PetscCall(PetscLayoutSetUp(mat->rmap)); 11213 PetscCall(PetscLayoutSetUp(mat->cmap)); 11214 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11215 if (*cong) mat->congruentlayouts = 1; 11216 else mat->congruentlayouts = 0; 11217 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11218 PetscFunctionReturn(PETSC_SUCCESS); 11219 } 11220 11221 PetscErrorCode MatSetInf(Mat A) 11222 { 11223 PetscFunctionBegin; 11224 PetscUseTypeMethod(A, setinf); 11225 PetscFunctionReturn(PETSC_SUCCESS); 11226 } 11227 11228 /*@ 11229 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 11230 and possibly removes small values from the graph structure. 11231 11232 Collective 11233 11234 Input Parameters: 11235 + A - the matrix 11236 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11237 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11238 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11239 . num_idx - size of 'index' array 11240 - index - array of block indices to use for graph strength of connection weight 11241 11242 Output Parameter: 11243 . graph - the resulting graph 11244 11245 Level: advanced 11246 11247 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11248 @*/ 11249 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11250 { 11251 PetscFunctionBegin; 11252 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11253 PetscValidType(A, 1); 11254 PetscValidLogicalCollectiveBool(A, scale, 3); 11255 PetscAssertPointer(graph, 7); 11256 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11257 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11258 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11259 PetscFunctionReturn(PETSC_SUCCESS); 11260 } 11261 11262 /*@ 11263 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11264 meaning the same memory is used for the matrix, and no new memory is allocated. 11265 11266 Collective 11267 11268 Input Parameters: 11269 + A - the matrix 11270 - 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 11271 11272 Level: intermediate 11273 11274 Developer Note: 11275 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11276 of the arrays in the data structure are unneeded. 11277 11278 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11279 @*/ 11280 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11281 { 11282 PetscFunctionBegin; 11283 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11284 PetscUseTypeMethod(A, eliminatezeros, keep); 11285 PetscFunctionReturn(PETSC_SUCCESS); 11286 } 11287