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 . v - a logically two-dimensional array of values 1513 . m - the number of rows 1514 . idxm - the global indices of the rows 1515 . n - the number of columns 1516 . idxn - the global indices of the columns 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 row-oriented. See `MatSetOption()` for other options. 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 . v - a logically two-dimensional array of values 1609 . ism - the rows to provide 1610 . isn - the columns to provide 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 row-oriented. See `MatSetOption()` for other options. 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 Developer Note: 1637 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1638 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1639 1640 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1641 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1642 @*/ 1643 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1644 { 1645 PetscInt m, n; 1646 const PetscInt *rows, *cols; 1647 1648 PetscFunctionBeginHot; 1649 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1650 PetscCall(ISGetIndices(ism, &rows)); 1651 PetscCall(ISGetIndices(isn, &cols)); 1652 PetscCall(ISGetLocalSize(ism, &m)); 1653 PetscCall(ISGetLocalSize(isn, &n)); 1654 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1655 PetscCall(ISRestoreIndices(ism, &rows)); 1656 PetscCall(ISRestoreIndices(isn, &cols)); 1657 PetscFunctionReturn(PETSC_SUCCESS); 1658 } 1659 1660 /*@ 1661 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1662 values into a matrix 1663 1664 Not Collective 1665 1666 Input Parameters: 1667 + mat - the matrix 1668 . row - the (block) row to set 1669 - v - a logically two-dimensional array of values 1670 1671 Level: intermediate 1672 1673 Notes: 1674 The values, `v`, are column-oriented (for the block version) and sorted 1675 1676 All the nonzero values in `row` must be provided 1677 1678 The matrix must have previously had its column indices set, likely by having been assembled. 1679 1680 `row` must belong to this MPI process 1681 1682 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1683 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1684 @*/ 1685 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1686 { 1687 PetscInt globalrow; 1688 1689 PetscFunctionBegin; 1690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1691 PetscValidType(mat, 1); 1692 PetscAssertPointer(v, 3); 1693 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1694 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1695 PetscFunctionReturn(PETSC_SUCCESS); 1696 } 1697 1698 /*@ 1699 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1700 values into a matrix 1701 1702 Not Collective 1703 1704 Input Parameters: 1705 + mat - the matrix 1706 . row - the (block) row to set 1707 - 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 1708 1709 Level: advanced 1710 1711 Notes: 1712 The values, `v`, are column-oriented for the block version. 1713 1714 All the nonzeros in `row` must be provided 1715 1716 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1717 1718 `row` must belong to this process 1719 1720 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1721 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1722 @*/ 1723 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1724 { 1725 PetscFunctionBeginHot; 1726 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1727 PetscValidType(mat, 1); 1728 MatCheckPreallocated(mat, 1); 1729 PetscAssertPointer(v, 3); 1730 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1731 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1732 mat->insertmode = INSERT_VALUES; 1733 1734 if (mat->assembled) { 1735 mat->was_assembled = PETSC_TRUE; 1736 mat->assembled = PETSC_FALSE; 1737 } 1738 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1739 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1740 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1741 PetscFunctionReturn(PETSC_SUCCESS); 1742 } 1743 1744 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1745 /*@ 1746 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1747 Using structured grid indexing 1748 1749 Not Collective 1750 1751 Input Parameters: 1752 + mat - the matrix 1753 . m - number of rows being entered 1754 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1755 . n - number of columns being entered 1756 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1757 . v - a logically two-dimensional array of values 1758 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1759 1760 Level: beginner 1761 1762 Notes: 1763 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1764 1765 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1766 options cannot be mixed without intervening calls to the assembly 1767 routines. 1768 1769 The grid coordinates are across the entire grid, not just the local portion 1770 1771 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1772 as well as in C. 1773 1774 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1775 1776 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1777 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1778 1779 The columns and rows in the stencil passed in MUST be contained within the 1780 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1781 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1782 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1783 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1784 1785 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1786 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1787 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1788 `DM_BOUNDARY_PERIODIC` boundary type. 1789 1790 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 1791 a single value per point) you can skip filling those indices. 1792 1793 Inspired by the structured grid interface to the HYPRE package 1794 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1795 1796 Efficiency Alert: 1797 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1798 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1799 1800 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1801 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1802 @*/ 1803 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1804 { 1805 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1806 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1807 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1808 1809 PetscFunctionBegin; 1810 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1811 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1812 PetscValidType(mat, 1); 1813 PetscAssertPointer(idxm, 3); 1814 PetscAssertPointer(idxn, 5); 1815 1816 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1817 jdxm = buf; 1818 jdxn = buf + m; 1819 } else { 1820 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1821 jdxm = bufm; 1822 jdxn = bufn; 1823 } 1824 for (i = 0; i < m; i++) { 1825 for (j = 0; j < 3 - sdim; j++) dxm++; 1826 tmp = *dxm++ - starts[0]; 1827 for (j = 0; j < dim - 1; j++) { 1828 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1829 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1830 } 1831 if (mat->stencil.noc) dxm++; 1832 jdxm[i] = tmp; 1833 } 1834 for (i = 0; i < n; i++) { 1835 for (j = 0; j < 3 - sdim; j++) dxn++; 1836 tmp = *dxn++ - starts[0]; 1837 for (j = 0; j < dim - 1; j++) { 1838 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1839 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1840 } 1841 if (mat->stencil.noc) dxn++; 1842 jdxn[i] = tmp; 1843 } 1844 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1845 PetscCall(PetscFree2(bufm, bufn)); 1846 PetscFunctionReturn(PETSC_SUCCESS); 1847 } 1848 1849 /*@ 1850 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1851 Using structured grid indexing 1852 1853 Not Collective 1854 1855 Input Parameters: 1856 + mat - the matrix 1857 . m - number of rows being entered 1858 . idxm - grid coordinates for matrix rows being entered 1859 . n - number of columns being entered 1860 . idxn - grid coordinates for matrix columns being entered 1861 . v - a logically two-dimensional array of values 1862 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1863 1864 Level: beginner 1865 1866 Notes: 1867 By default the values, `v`, are row-oriented and unsorted. 1868 See `MatSetOption()` for other options. 1869 1870 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1871 options cannot be mixed without intervening calls to the assembly 1872 routines. 1873 1874 The grid coordinates are across the entire grid, not just the local portion 1875 1876 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1877 as well as in C. 1878 1879 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1880 1881 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1882 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1883 1884 The columns and rows in the stencil passed in MUST be contained within the 1885 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1886 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1887 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1888 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1889 1890 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1891 simply ignored. This allows easily inserting element stiffness matrices 1892 with homogeneous Dirichlet boundary conditions that you don't want represented 1893 in the matrix. 1894 1895 Inspired by the structured grid interface to the HYPRE package 1896 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1897 1898 Fortran Note: 1899 `idxm` and `idxn` should be declared as 1900 .vb 1901 MatStencil idxm(4,m),idxn(4,n) 1902 .ve 1903 and the values inserted using 1904 .vb 1905 idxm(MatStencil_i,1) = i 1906 idxm(MatStencil_j,1) = j 1907 idxm(MatStencil_k,1) = k 1908 etc 1909 .ve 1910 1911 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1912 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1913 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1914 @*/ 1915 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1916 { 1917 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1918 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1919 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1920 1921 PetscFunctionBegin; 1922 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1923 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1924 PetscValidType(mat, 1); 1925 PetscAssertPointer(idxm, 3); 1926 PetscAssertPointer(idxn, 5); 1927 PetscAssertPointer(v, 6); 1928 1929 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1930 jdxm = buf; 1931 jdxn = buf + m; 1932 } else { 1933 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1934 jdxm = bufm; 1935 jdxn = bufn; 1936 } 1937 for (i = 0; i < m; i++) { 1938 for (j = 0; j < 3 - sdim; j++) dxm++; 1939 tmp = *dxm++ - starts[0]; 1940 for (j = 0; j < sdim - 1; j++) { 1941 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1942 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1943 } 1944 dxm++; 1945 jdxm[i] = tmp; 1946 } 1947 for (i = 0; i < n; i++) { 1948 for (j = 0; j < 3 - sdim; j++) dxn++; 1949 tmp = *dxn++ - starts[0]; 1950 for (j = 0; j < sdim - 1; j++) { 1951 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1952 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1953 } 1954 dxn++; 1955 jdxn[i] = tmp; 1956 } 1957 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1958 PetscCall(PetscFree2(bufm, bufn)); 1959 PetscFunctionReturn(PETSC_SUCCESS); 1960 } 1961 1962 /*@ 1963 MatSetStencil - Sets the grid information for setting values into a matrix via 1964 `MatSetValuesStencil()` 1965 1966 Not Collective 1967 1968 Input Parameters: 1969 + mat - the matrix 1970 . dim - dimension of the grid 1, 2, or 3 1971 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1972 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1973 - dof - number of degrees of freedom per node 1974 1975 Level: beginner 1976 1977 Notes: 1978 Inspired by the structured grid interface to the HYPRE package 1979 (www.llnl.gov/CASC/hyper) 1980 1981 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1982 user. 1983 1984 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1985 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1986 @*/ 1987 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1988 { 1989 PetscFunctionBegin; 1990 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1991 PetscAssertPointer(dims, 3); 1992 PetscAssertPointer(starts, 4); 1993 1994 mat->stencil.dim = dim + (dof > 1); 1995 for (PetscInt i = 0; i < dim; i++) { 1996 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1997 mat->stencil.starts[i] = starts[dim - i - 1]; 1998 } 1999 mat->stencil.dims[dim] = dof; 2000 mat->stencil.starts[dim] = 0; 2001 mat->stencil.noc = (PetscBool)(dof == 1); 2002 PetscFunctionReturn(PETSC_SUCCESS); 2003 } 2004 2005 /*@ 2006 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 2007 2008 Not Collective 2009 2010 Input Parameters: 2011 + mat - the matrix 2012 . v - a logically two-dimensional array of values 2013 . m - the number of block rows 2014 . idxm - the global block indices 2015 . n - the number of block columns 2016 . idxn - the global block indices 2017 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2018 2019 Level: intermediate 2020 2021 Notes: 2022 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2023 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2024 2025 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2026 NOT the total number of rows/columns; for example, if the block size is 2 and 2027 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2028 The values in `idxm` would be 1 2; that is the first index for each block divided by 2029 the block size. 2030 2031 You must call `MatSetBlockSize()` when constructing this matrix (before 2032 preallocating it). 2033 2034 By default the values, `v`, are row-oriented, so the layout of 2035 `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options. 2036 2037 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2038 options cannot be mixed without intervening calls to the assembly 2039 routines. 2040 2041 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2042 as well as in C. 2043 2044 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2045 simply ignored. This allows easily inserting element stiffness matrices 2046 with homogeneous Dirichlet boundary conditions that you don't want represented 2047 in the matrix. 2048 2049 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2050 internal searching must be done to determine where to place the 2051 data in the matrix storage space. By instead inserting blocks of 2052 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2053 reduced. 2054 2055 Example: 2056 .vb 2057 Suppose m=n=2 and block size(bs) = 2 The array is 2058 2059 1 2 | 3 4 2060 5 6 | 7 8 2061 - - - | - - - 2062 9 10 | 11 12 2063 13 14 | 15 16 2064 2065 v[] should be passed in like 2066 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2067 2068 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2069 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2070 .ve 2071 2072 Fortran Notes: 2073 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2074 .vb 2075 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2076 .ve 2077 2078 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2079 2080 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2081 @*/ 2082 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2083 { 2084 PetscFunctionBeginHot; 2085 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2086 PetscValidType(mat, 1); 2087 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2088 PetscAssertPointer(idxm, 3); 2089 PetscAssertPointer(idxn, 5); 2090 MatCheckPreallocated(mat, 1); 2091 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2092 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2093 if (PetscDefined(USE_DEBUG)) { 2094 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2095 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2096 } 2097 if (PetscDefined(USE_DEBUG)) { 2098 PetscInt rbs, cbs, M, N, i; 2099 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2100 PetscCall(MatGetSize(mat, &M, &N)); 2101 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); 2102 for (i = 0; i < n; i++) 2103 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); 2104 } 2105 if (mat->assembled) { 2106 mat->was_assembled = PETSC_TRUE; 2107 mat->assembled = PETSC_FALSE; 2108 } 2109 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2110 if (mat->ops->setvaluesblocked) { 2111 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2112 } else { 2113 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2114 PetscInt i, j, bs, cbs; 2115 2116 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2117 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2118 iidxm = buf; 2119 iidxn = buf + m * bs; 2120 } else { 2121 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2122 iidxm = bufr; 2123 iidxn = bufc; 2124 } 2125 for (i = 0; i < m; i++) { 2126 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2127 } 2128 if (m != n || bs != cbs || idxm != idxn) { 2129 for (i = 0; i < n; i++) { 2130 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2131 } 2132 } else iidxn = iidxm; 2133 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2134 PetscCall(PetscFree2(bufr, bufc)); 2135 } 2136 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2137 PetscFunctionReturn(PETSC_SUCCESS); 2138 } 2139 2140 /*@ 2141 MatGetValues - Gets a block of local values from a matrix. 2142 2143 Not Collective; can only return values that are owned by the give process 2144 2145 Input Parameters: 2146 + mat - the matrix 2147 . v - a logically two-dimensional array for storing the values 2148 . m - the number of rows 2149 . idxm - the global indices of the rows 2150 . n - the number of columns 2151 - idxn - the global indices of the columns 2152 2153 Level: advanced 2154 2155 Notes: 2156 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2157 The values, `v`, are then returned in a row-oriented format, 2158 analogous to that used by default in `MatSetValues()`. 2159 2160 `MatGetValues()` uses 0-based row and column numbers in 2161 Fortran as well as in C. 2162 2163 `MatGetValues()` requires that the matrix has been assembled 2164 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2165 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2166 without intermediate matrix assembly. 2167 2168 Negative row or column indices will be ignored and those locations in `v` will be 2169 left unchanged. 2170 2171 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2172 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2173 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2174 2175 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2176 @*/ 2177 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2178 { 2179 PetscFunctionBegin; 2180 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2181 PetscValidType(mat, 1); 2182 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2183 PetscAssertPointer(idxm, 3); 2184 PetscAssertPointer(idxn, 5); 2185 PetscAssertPointer(v, 6); 2186 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2187 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2188 MatCheckPreallocated(mat, 1); 2189 2190 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2191 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2192 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2193 PetscFunctionReturn(PETSC_SUCCESS); 2194 } 2195 2196 /*@ 2197 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2198 defined previously by `MatSetLocalToGlobalMapping()` 2199 2200 Not Collective 2201 2202 Input Parameters: 2203 + mat - the matrix 2204 . nrow - number of rows 2205 . irow - the row local indices 2206 . ncol - number of columns 2207 - icol - the column local indices 2208 2209 Output Parameter: 2210 . y - a logically two-dimensional array of values 2211 2212 Level: advanced 2213 2214 Notes: 2215 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2216 2217 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, 2218 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2219 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2220 with `MatSetLocalToGlobalMapping()`. 2221 2222 Developer Note: 2223 This is labelled with C so does not automatically generate Fortran stubs and interfaces 2224 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 2225 2226 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2227 `MatSetValuesLocal()`, `MatGetValues()` 2228 @*/ 2229 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2230 { 2231 PetscFunctionBeginHot; 2232 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2233 PetscValidType(mat, 1); 2234 MatCheckPreallocated(mat, 1); 2235 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2236 PetscAssertPointer(irow, 3); 2237 PetscAssertPointer(icol, 5); 2238 if (PetscDefined(USE_DEBUG)) { 2239 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2240 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2241 } 2242 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2243 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2244 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2245 else { 2246 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2247 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2248 irowm = buf; 2249 icolm = buf + nrow; 2250 } else { 2251 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2252 irowm = bufr; 2253 icolm = bufc; 2254 } 2255 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2256 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2257 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2258 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2259 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2260 PetscCall(PetscFree2(bufr, bufc)); 2261 } 2262 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2263 PetscFunctionReturn(PETSC_SUCCESS); 2264 } 2265 2266 /*@ 2267 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2268 the same size. Currently, this can only be called once and creates the given matrix. 2269 2270 Not Collective 2271 2272 Input Parameters: 2273 + mat - the matrix 2274 . nb - the number of blocks 2275 . bs - the number of rows (and columns) in each block 2276 . rows - a concatenation of the rows for each block 2277 - v - a concatenation of logically two-dimensional arrays of values 2278 2279 Level: advanced 2280 2281 Notes: 2282 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2283 2284 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2285 2286 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2287 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2288 @*/ 2289 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2290 { 2291 PetscFunctionBegin; 2292 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2293 PetscValidType(mat, 1); 2294 PetscAssertPointer(rows, 4); 2295 PetscAssertPointer(v, 5); 2296 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2297 2298 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2299 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2300 else { 2301 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2302 } 2303 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2304 PetscFunctionReturn(PETSC_SUCCESS); 2305 } 2306 2307 /*@ 2308 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2309 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2310 using a local (per-processor) numbering. 2311 2312 Not Collective 2313 2314 Input Parameters: 2315 + x - the matrix 2316 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2317 - cmapping - column mapping 2318 2319 Level: intermediate 2320 2321 Note: 2322 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2323 2324 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2325 @*/ 2326 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2327 { 2328 PetscFunctionBegin; 2329 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2330 PetscValidType(x, 1); 2331 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2332 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2333 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2334 else { 2335 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2336 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2337 } 2338 PetscFunctionReturn(PETSC_SUCCESS); 2339 } 2340 2341 /*@ 2342 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2343 2344 Not Collective 2345 2346 Input Parameter: 2347 . A - the matrix 2348 2349 Output Parameters: 2350 + rmapping - row mapping 2351 - cmapping - column mapping 2352 2353 Level: advanced 2354 2355 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2356 @*/ 2357 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2358 { 2359 PetscFunctionBegin; 2360 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2361 PetscValidType(A, 1); 2362 if (rmapping) { 2363 PetscAssertPointer(rmapping, 2); 2364 *rmapping = A->rmap->mapping; 2365 } 2366 if (cmapping) { 2367 PetscAssertPointer(cmapping, 3); 2368 *cmapping = A->cmap->mapping; 2369 } 2370 PetscFunctionReturn(PETSC_SUCCESS); 2371 } 2372 2373 /*@ 2374 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2375 2376 Logically Collective 2377 2378 Input Parameters: 2379 + A - the matrix 2380 . rmap - row layout 2381 - cmap - column layout 2382 2383 Level: advanced 2384 2385 Note: 2386 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2387 2388 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2389 @*/ 2390 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2391 { 2392 PetscFunctionBegin; 2393 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2394 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2395 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2396 PetscFunctionReturn(PETSC_SUCCESS); 2397 } 2398 2399 /*@ 2400 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2401 2402 Not Collective 2403 2404 Input Parameter: 2405 . A - the matrix 2406 2407 Output Parameters: 2408 + rmap - row layout 2409 - cmap - column layout 2410 2411 Level: advanced 2412 2413 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2414 @*/ 2415 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2416 { 2417 PetscFunctionBegin; 2418 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2419 PetscValidType(A, 1); 2420 if (rmap) { 2421 PetscAssertPointer(rmap, 2); 2422 *rmap = A->rmap; 2423 } 2424 if (cmap) { 2425 PetscAssertPointer(cmap, 3); 2426 *cmap = A->cmap; 2427 } 2428 PetscFunctionReturn(PETSC_SUCCESS); 2429 } 2430 2431 /*@ 2432 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2433 using a local numbering of the rows and columns. 2434 2435 Not Collective 2436 2437 Input Parameters: 2438 + mat - the matrix 2439 . nrow - number of rows 2440 . irow - the row local indices 2441 . ncol - number of columns 2442 . icol - the column local indices 2443 . y - a logically two-dimensional array of values 2444 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2445 2446 Level: intermediate 2447 2448 Notes: 2449 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2450 2451 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2452 options cannot be mixed without intervening calls to the assembly 2453 routines. 2454 2455 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2456 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2457 2458 Fortran Notes: 2459 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2460 .vb 2461 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2462 .ve 2463 2464 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2465 2466 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2467 `MatGetValuesLocal()` 2468 @*/ 2469 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2470 { 2471 PetscFunctionBeginHot; 2472 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2473 PetscValidType(mat, 1); 2474 MatCheckPreallocated(mat, 1); 2475 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2476 PetscAssertPointer(irow, 3); 2477 PetscAssertPointer(icol, 5); 2478 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2479 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2480 if (PetscDefined(USE_DEBUG)) { 2481 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2482 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2483 } 2484 2485 if (mat->assembled) { 2486 mat->was_assembled = PETSC_TRUE; 2487 mat->assembled = PETSC_FALSE; 2488 } 2489 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2490 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2491 else { 2492 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2493 const PetscInt *irowm, *icolm; 2494 2495 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2496 bufr = buf; 2497 bufc = buf + nrow; 2498 irowm = bufr; 2499 icolm = bufc; 2500 } else { 2501 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2502 irowm = bufr; 2503 icolm = bufc; 2504 } 2505 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2506 else irowm = irow; 2507 if (mat->cmap->mapping) { 2508 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2509 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2510 } else icolm = irowm; 2511 } else icolm = icol; 2512 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2513 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2514 } 2515 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2516 PetscFunctionReturn(PETSC_SUCCESS); 2517 } 2518 2519 /*@ 2520 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2521 using a local ordering of the nodes a block at a time. 2522 2523 Not Collective 2524 2525 Input Parameters: 2526 + mat - the matrix 2527 . nrow - number of rows 2528 . irow - the row local indices 2529 . ncol - number of columns 2530 . icol - the column local indices 2531 . y - a logically two-dimensional array of values 2532 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2533 2534 Level: intermediate 2535 2536 Notes: 2537 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2538 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2539 2540 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2541 options cannot be mixed without intervening calls to the assembly 2542 routines. 2543 2544 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2545 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2546 2547 Fortran Notes: 2548 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2549 .vb 2550 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2551 .ve 2552 2553 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2554 2555 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2556 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2557 @*/ 2558 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2559 { 2560 PetscFunctionBeginHot; 2561 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2562 PetscValidType(mat, 1); 2563 MatCheckPreallocated(mat, 1); 2564 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2565 PetscAssertPointer(irow, 3); 2566 PetscAssertPointer(icol, 5); 2567 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2568 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2569 if (PetscDefined(USE_DEBUG)) { 2570 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2571 PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2572 } 2573 2574 if (mat->assembled) { 2575 mat->was_assembled = PETSC_TRUE; 2576 mat->assembled = PETSC_FALSE; 2577 } 2578 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2579 PetscInt irbs, rbs; 2580 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2581 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2582 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2583 } 2584 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2585 PetscInt icbs, cbs; 2586 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2587 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2588 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2589 } 2590 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2591 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2592 else { 2593 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2594 const PetscInt *irowm, *icolm; 2595 2596 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2597 bufr = buf; 2598 bufc = buf + nrow; 2599 irowm = bufr; 2600 icolm = bufc; 2601 } else { 2602 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2603 irowm = bufr; 2604 icolm = bufc; 2605 } 2606 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2607 else irowm = irow; 2608 if (mat->cmap->mapping) { 2609 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) { 2610 PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2611 } else icolm = irowm; 2612 } else icolm = icol; 2613 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2614 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2615 } 2616 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2617 PetscFunctionReturn(PETSC_SUCCESS); 2618 } 2619 2620 /*@ 2621 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2622 2623 Collective 2624 2625 Input Parameters: 2626 + mat - the matrix 2627 - x - the vector to be multiplied 2628 2629 Output Parameter: 2630 . y - the result 2631 2632 Level: developer 2633 2634 Note: 2635 The vectors `x` and `y` cannot be the same. I.e., one cannot 2636 call `MatMultDiagonalBlock`(A,y,y). 2637 2638 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2639 @*/ 2640 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2641 { 2642 PetscFunctionBegin; 2643 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2644 PetscValidType(mat, 1); 2645 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2646 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2647 2648 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2649 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2650 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2651 MatCheckPreallocated(mat, 1); 2652 2653 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2654 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2655 PetscFunctionReturn(PETSC_SUCCESS); 2656 } 2657 2658 /*@ 2659 MatMult - Computes the matrix-vector product, $y = Ax$. 2660 2661 Neighbor-wise Collective 2662 2663 Input Parameters: 2664 + mat - the matrix 2665 - x - the vector to be multiplied 2666 2667 Output Parameter: 2668 . y - the result 2669 2670 Level: beginner 2671 2672 Note: 2673 The vectors `x` and `y` cannot be the same. I.e., one cannot 2674 call `MatMult`(A,y,y). 2675 2676 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2677 @*/ 2678 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2679 { 2680 PetscFunctionBegin; 2681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2682 PetscValidType(mat, 1); 2683 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2684 VecCheckAssembled(x); 2685 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2686 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2687 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2688 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2689 PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N); 2690 PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N); 2691 PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n); 2692 PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n); 2693 PetscCall(VecSetErrorIfLocked(y, 3)); 2694 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2695 MatCheckPreallocated(mat, 1); 2696 2697 PetscCall(VecLockReadPush(x)); 2698 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2699 PetscUseTypeMethod(mat, mult, x, y); 2700 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2701 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2702 PetscCall(VecLockReadPop(x)); 2703 PetscFunctionReturn(PETSC_SUCCESS); 2704 } 2705 2706 /*@ 2707 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2708 2709 Neighbor-wise Collective 2710 2711 Input Parameters: 2712 + mat - the matrix 2713 - x - the vector to be multiplied 2714 2715 Output Parameter: 2716 . y - the result 2717 2718 Level: beginner 2719 2720 Notes: 2721 The vectors `x` and `y` cannot be the same. I.e., one cannot 2722 call `MatMultTranspose`(A,y,y). 2723 2724 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2725 use `MatMultHermitianTranspose()` 2726 2727 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2728 @*/ 2729 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2730 { 2731 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2732 2733 PetscFunctionBegin; 2734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2735 PetscValidType(mat, 1); 2736 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2737 VecCheckAssembled(x); 2738 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2739 2740 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2741 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2742 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2743 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2744 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2745 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2746 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2747 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2748 MatCheckPreallocated(mat, 1); 2749 2750 if (!mat->ops->multtranspose) { 2751 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2752 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name); 2753 } else op = mat->ops->multtranspose; 2754 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2755 PetscCall(VecLockReadPush(x)); 2756 PetscCall((*op)(mat, x, y)); 2757 PetscCall(VecLockReadPop(x)); 2758 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2759 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2760 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2761 PetscFunctionReturn(PETSC_SUCCESS); 2762 } 2763 2764 /*@ 2765 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2766 2767 Neighbor-wise Collective 2768 2769 Input Parameters: 2770 + mat - the matrix 2771 - x - the vector to be multiplied 2772 2773 Output Parameter: 2774 . y - the result 2775 2776 Level: beginner 2777 2778 Notes: 2779 The vectors `x` and `y` cannot be the same. I.e., one cannot 2780 call `MatMultHermitianTranspose`(A,y,y). 2781 2782 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2783 2784 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2785 2786 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2787 @*/ 2788 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2789 { 2790 PetscFunctionBegin; 2791 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2792 PetscValidType(mat, 1); 2793 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2794 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2795 2796 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2797 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2798 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2799 PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N); 2800 PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N); 2801 PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n); 2802 PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n); 2803 MatCheckPreallocated(mat, 1); 2804 2805 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2806 #if defined(PETSC_USE_COMPLEX) 2807 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2808 PetscCall(VecLockReadPush(x)); 2809 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2810 else PetscUseTypeMethod(mat, mult, x, y); 2811 PetscCall(VecLockReadPop(x)); 2812 } else { 2813 Vec w; 2814 PetscCall(VecDuplicate(x, &w)); 2815 PetscCall(VecCopy(x, w)); 2816 PetscCall(VecConjugate(w)); 2817 PetscCall(MatMultTranspose(mat, w, y)); 2818 PetscCall(VecDestroy(&w)); 2819 PetscCall(VecConjugate(y)); 2820 } 2821 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2822 #else 2823 PetscCall(MatMultTranspose(mat, x, y)); 2824 #endif 2825 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2826 PetscFunctionReturn(PETSC_SUCCESS); 2827 } 2828 2829 /*@ 2830 MatMultAdd - Computes $v3 = v2 + A * v1$. 2831 2832 Neighbor-wise Collective 2833 2834 Input Parameters: 2835 + mat - the matrix 2836 . v1 - the vector to be multiplied by `mat` 2837 - v2 - the vector to be added to the result 2838 2839 Output Parameter: 2840 . v3 - the result 2841 2842 Level: beginner 2843 2844 Note: 2845 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2846 call `MatMultAdd`(A,v1,v2,v1). 2847 2848 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2849 @*/ 2850 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2851 { 2852 PetscFunctionBegin; 2853 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2854 PetscValidType(mat, 1); 2855 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2856 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2857 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2858 2859 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2860 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2861 PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N); 2862 /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N); 2863 PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */ 2864 PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n); 2865 PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n); 2866 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2867 MatCheckPreallocated(mat, 1); 2868 2869 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2870 PetscCall(VecLockReadPush(v1)); 2871 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2872 PetscCall(VecLockReadPop(v1)); 2873 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2874 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2875 PetscFunctionReturn(PETSC_SUCCESS); 2876 } 2877 2878 /*@ 2879 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2880 2881 Neighbor-wise Collective 2882 2883 Input Parameters: 2884 + mat - the matrix 2885 . v1 - the vector to be multiplied by the transpose of the matrix 2886 - v2 - the vector to be added to the result 2887 2888 Output Parameter: 2889 . v3 - the result 2890 2891 Level: beginner 2892 2893 Note: 2894 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2895 call `MatMultTransposeAdd`(A,v1,v2,v1). 2896 2897 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2898 @*/ 2899 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2900 { 2901 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2902 2903 PetscFunctionBegin; 2904 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2905 PetscValidType(mat, 1); 2906 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2907 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2908 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2909 2910 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2911 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2912 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2913 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2914 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2915 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2916 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2917 MatCheckPreallocated(mat, 1); 2918 2919 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2920 PetscCall(VecLockReadPush(v1)); 2921 PetscCall((*op)(mat, v1, v2, v3)); 2922 PetscCall(VecLockReadPop(v1)); 2923 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2924 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2925 PetscFunctionReturn(PETSC_SUCCESS); 2926 } 2927 2928 /*@ 2929 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2930 2931 Neighbor-wise Collective 2932 2933 Input Parameters: 2934 + mat - the matrix 2935 . v1 - the vector to be multiplied by the Hermitian transpose 2936 - v2 - the vector to be added to the result 2937 2938 Output Parameter: 2939 . v3 - the result 2940 2941 Level: beginner 2942 2943 Note: 2944 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2945 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2946 2947 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2948 @*/ 2949 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2950 { 2951 PetscFunctionBegin; 2952 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2953 PetscValidType(mat, 1); 2954 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2955 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2956 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2957 2958 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2959 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2960 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2961 PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N); 2962 PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N); 2963 PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N); 2964 MatCheckPreallocated(mat, 1); 2965 2966 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2967 PetscCall(VecLockReadPush(v1)); 2968 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2969 else { 2970 Vec w, z; 2971 PetscCall(VecDuplicate(v1, &w)); 2972 PetscCall(VecCopy(v1, w)); 2973 PetscCall(VecConjugate(w)); 2974 PetscCall(VecDuplicate(v3, &z)); 2975 PetscCall(MatMultTranspose(mat, w, z)); 2976 PetscCall(VecDestroy(&w)); 2977 PetscCall(VecConjugate(z)); 2978 if (v2 != v3) { 2979 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2980 } else { 2981 PetscCall(VecAXPY(v3, 1.0, z)); 2982 } 2983 PetscCall(VecDestroy(&z)); 2984 } 2985 PetscCall(VecLockReadPop(v1)); 2986 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2987 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2988 PetscFunctionReturn(PETSC_SUCCESS); 2989 } 2990 2991 /*@ 2992 MatGetFactorType - gets the type of factorization a matrix is 2993 2994 Not Collective 2995 2996 Input Parameter: 2997 . mat - the matrix 2998 2999 Output Parameter: 3000 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3001 3002 Level: intermediate 3003 3004 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3005 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3006 @*/ 3007 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 3008 { 3009 PetscFunctionBegin; 3010 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3011 PetscValidType(mat, 1); 3012 PetscAssertPointer(t, 2); 3013 *t = mat->factortype; 3014 PetscFunctionReturn(PETSC_SUCCESS); 3015 } 3016 3017 /*@ 3018 MatSetFactorType - sets the type of factorization a matrix is 3019 3020 Logically Collective 3021 3022 Input Parameters: 3023 + mat - the matrix 3024 - t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3025 3026 Level: intermediate 3027 3028 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3029 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3030 @*/ 3031 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3032 { 3033 PetscFunctionBegin; 3034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3035 PetscValidType(mat, 1); 3036 mat->factortype = t; 3037 PetscFunctionReturn(PETSC_SUCCESS); 3038 } 3039 3040 /*@ 3041 MatGetInfo - Returns information about matrix storage (number of 3042 nonzeros, memory, etc.). 3043 3044 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3045 3046 Input Parameters: 3047 + mat - the matrix 3048 - flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors) 3049 3050 Output Parameter: 3051 . info - matrix information context 3052 3053 Options Database Key: 3054 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3055 3056 Level: intermediate 3057 3058 Notes: 3059 The `MatInfo` context contains a variety of matrix data, including 3060 number of nonzeros allocated and used, number of mallocs during 3061 matrix assembly, etc. Additional information for factored matrices 3062 is provided (such as the fill ratio, number of mallocs during 3063 factorization, etc.). 3064 3065 Example: 3066 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3067 data within the `MatInfo` context. For example, 3068 .vb 3069 MatInfo info; 3070 Mat A; 3071 double mal, nz_a, nz_u; 3072 3073 MatGetInfo(A, MAT_LOCAL, &info); 3074 mal = info.mallocs; 3075 nz_a = info.nz_allocated; 3076 .ve 3077 3078 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3079 @*/ 3080 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3081 { 3082 PetscFunctionBegin; 3083 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3084 PetscValidType(mat, 1); 3085 PetscAssertPointer(info, 3); 3086 MatCheckPreallocated(mat, 1); 3087 PetscUseTypeMethod(mat, getinfo, flag, info); 3088 PetscFunctionReturn(PETSC_SUCCESS); 3089 } 3090 3091 /* 3092 This is used by external packages where it is not easy to get the info from the actual 3093 matrix factorization. 3094 */ 3095 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3096 { 3097 PetscFunctionBegin; 3098 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3099 PetscFunctionReturn(PETSC_SUCCESS); 3100 } 3101 3102 /*@ 3103 MatLUFactor - Performs in-place LU factorization of matrix. 3104 3105 Collective 3106 3107 Input Parameters: 3108 + mat - the matrix 3109 . row - row permutation 3110 . col - column permutation 3111 - info - options for factorization, includes 3112 .vb 3113 fill - expected fill as ratio of original fill. 3114 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3115 Run with the option -info to determine an optimal value to use 3116 .ve 3117 3118 Level: developer 3119 3120 Notes: 3121 Most users should employ the `KSP` interface for linear solvers 3122 instead of working directly with matrix algebra routines such as this. 3123 See, e.g., `KSPCreate()`. 3124 3125 This changes the state of the matrix to a factored matrix; it cannot be used 3126 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3127 3128 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3129 when not using `KSP`. 3130 3131 Developer Note: 3132 The Fortran interface is not autogenerated as the 3133 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3134 3135 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3136 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3137 @*/ 3138 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3139 { 3140 MatFactorInfo tinfo; 3141 3142 PetscFunctionBegin; 3143 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3144 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3145 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3146 if (info) PetscAssertPointer(info, 4); 3147 PetscValidType(mat, 1); 3148 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3149 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3150 MatCheckPreallocated(mat, 1); 3151 if (!info) { 3152 PetscCall(MatFactorInfoInitialize(&tinfo)); 3153 info = &tinfo; 3154 } 3155 3156 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3157 PetscUseTypeMethod(mat, lufactor, row, col, info); 3158 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3159 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3160 PetscFunctionReturn(PETSC_SUCCESS); 3161 } 3162 3163 /*@ 3164 MatILUFactor - Performs in-place ILU factorization of matrix. 3165 3166 Collective 3167 3168 Input Parameters: 3169 + mat - the matrix 3170 . row - row permutation 3171 . col - column permutation 3172 - info - structure containing 3173 .vb 3174 levels - number of levels of fill. 3175 expected fill - as ratio of original fill. 3176 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3177 missing diagonal entries) 3178 .ve 3179 3180 Level: developer 3181 3182 Notes: 3183 Most users should employ the `KSP` interface for linear solvers 3184 instead of working directly with matrix algebra routines such as this. 3185 See, e.g., `KSPCreate()`. 3186 3187 Probably really in-place only when level of fill is zero, otherwise allocates 3188 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3189 when not using `KSP`. 3190 3191 Developer Note: 3192 The Fortran interface is not autogenerated as the 3193 interface definition cannot be generated correctly [due to MatFactorInfo] 3194 3195 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3196 @*/ 3197 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3198 { 3199 PetscFunctionBegin; 3200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3201 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3202 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3203 PetscAssertPointer(info, 4); 3204 PetscValidType(mat, 1); 3205 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3206 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3207 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3208 MatCheckPreallocated(mat, 1); 3209 3210 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3211 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3212 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3214 PetscFunctionReturn(PETSC_SUCCESS); 3215 } 3216 3217 /*@ 3218 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3219 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3220 3221 Collective 3222 3223 Input Parameters: 3224 + fact - the factor matrix obtained with `MatGetFactor()` 3225 . mat - the matrix 3226 . row - the row permutation 3227 . col - the column permutation 3228 - info - options for factorization, includes 3229 .vb 3230 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3231 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3232 .ve 3233 3234 Level: developer 3235 3236 Notes: 3237 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3238 3239 Most users should employ the simplified `KSP` interface for linear solvers 3240 instead of working directly with matrix algebra routines such as this. 3241 See, e.g., `KSPCreate()`. 3242 3243 Developer Note: 3244 The Fortran interface is not autogenerated as the 3245 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3246 3247 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3248 @*/ 3249 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3250 { 3251 MatFactorInfo tinfo; 3252 3253 PetscFunctionBegin; 3254 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3255 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3256 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3257 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3258 if (info) PetscAssertPointer(info, 5); 3259 PetscValidType(fact, 1); 3260 PetscValidType(mat, 2); 3261 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3262 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3263 MatCheckPreallocated(mat, 2); 3264 if (!info) { 3265 PetscCall(MatFactorInfoInitialize(&tinfo)); 3266 info = &tinfo; 3267 } 3268 3269 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3270 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3271 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3272 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3273 PetscFunctionReturn(PETSC_SUCCESS); 3274 } 3275 3276 /*@ 3277 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3278 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3279 3280 Collective 3281 3282 Input Parameters: 3283 + fact - the factor matrix obtained with `MatGetFactor()` 3284 . mat - the matrix 3285 - info - options for factorization 3286 3287 Level: developer 3288 3289 Notes: 3290 See `MatLUFactor()` for in-place factorization. See 3291 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3292 3293 Most users should employ the `KSP` interface for linear solvers 3294 instead of working directly with matrix algebra routines such as this. 3295 See, e.g., `KSPCreate()`. 3296 3297 Developer Note: 3298 The Fortran interface is not autogenerated as the 3299 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3300 3301 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3302 @*/ 3303 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3304 { 3305 MatFactorInfo tinfo; 3306 3307 PetscFunctionBegin; 3308 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3309 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3310 PetscValidType(fact, 1); 3311 PetscValidType(mat, 2); 3312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3313 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, 3314 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3315 3316 MatCheckPreallocated(mat, 2); 3317 if (!info) { 3318 PetscCall(MatFactorInfoInitialize(&tinfo)); 3319 info = &tinfo; 3320 } 3321 3322 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3323 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3324 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3325 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3326 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3327 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3328 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3329 PetscFunctionReturn(PETSC_SUCCESS); 3330 } 3331 3332 /*@ 3333 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3334 symmetric matrix. 3335 3336 Collective 3337 3338 Input Parameters: 3339 + mat - the matrix 3340 . perm - row and column permutations 3341 - info - expected fill as ratio of original fill 3342 3343 Level: developer 3344 3345 Notes: 3346 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3347 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3348 3349 Most users should employ the `KSP` interface for linear solvers 3350 instead of working directly with matrix algebra routines such as this. 3351 See, e.g., `KSPCreate()`. 3352 3353 Developer Note: 3354 The Fortran interface is not autogenerated as the 3355 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3356 3357 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3358 `MatGetOrdering()` 3359 @*/ 3360 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3361 { 3362 MatFactorInfo tinfo; 3363 3364 PetscFunctionBegin; 3365 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3366 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3367 if (info) PetscAssertPointer(info, 3); 3368 PetscValidType(mat, 1); 3369 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3370 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3371 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3372 MatCheckPreallocated(mat, 1); 3373 if (!info) { 3374 PetscCall(MatFactorInfoInitialize(&tinfo)); 3375 info = &tinfo; 3376 } 3377 3378 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3379 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3380 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3381 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3382 PetscFunctionReturn(PETSC_SUCCESS); 3383 } 3384 3385 /*@ 3386 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3387 of a symmetric matrix. 3388 3389 Collective 3390 3391 Input Parameters: 3392 + fact - the factor matrix obtained with `MatGetFactor()` 3393 . mat - the matrix 3394 . perm - row and column permutations 3395 - info - options for factorization, includes 3396 .vb 3397 fill - expected fill as ratio of original fill. 3398 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3399 Run with the option -info to determine an optimal value to use 3400 .ve 3401 3402 Level: developer 3403 3404 Notes: 3405 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3406 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3407 3408 Most users should employ the `KSP` interface for linear solvers 3409 instead of working directly with matrix algebra routines such as this. 3410 See, e.g., `KSPCreate()`. 3411 3412 Developer Note: 3413 The Fortran interface is not autogenerated as the 3414 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3415 3416 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3417 `MatGetOrdering()` 3418 @*/ 3419 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3420 { 3421 MatFactorInfo tinfo; 3422 3423 PetscFunctionBegin; 3424 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3425 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3426 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3427 if (info) PetscAssertPointer(info, 4); 3428 PetscValidType(fact, 1); 3429 PetscValidType(mat, 2); 3430 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3431 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3432 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3433 MatCheckPreallocated(mat, 2); 3434 if (!info) { 3435 PetscCall(MatFactorInfoInitialize(&tinfo)); 3436 info = &tinfo; 3437 } 3438 3439 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3440 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3441 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3442 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3443 PetscFunctionReturn(PETSC_SUCCESS); 3444 } 3445 3446 /*@ 3447 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3448 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3449 `MatCholeskyFactorSymbolic()`. 3450 3451 Collective 3452 3453 Input Parameters: 3454 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3455 . mat - the initial matrix that is to be factored 3456 - info - options for factorization 3457 3458 Level: developer 3459 3460 Note: 3461 Most users should employ the `KSP` interface for linear solvers 3462 instead of working directly with matrix algebra routines such as this. 3463 See, e.g., `KSPCreate()`. 3464 3465 Developer Note: 3466 The Fortran interface is not autogenerated as the 3467 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3468 3469 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3470 @*/ 3471 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3472 { 3473 MatFactorInfo tinfo; 3474 3475 PetscFunctionBegin; 3476 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3477 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3478 PetscValidType(fact, 1); 3479 PetscValidType(mat, 2); 3480 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3481 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, 3482 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3483 MatCheckPreallocated(mat, 2); 3484 if (!info) { 3485 PetscCall(MatFactorInfoInitialize(&tinfo)); 3486 info = &tinfo; 3487 } 3488 3489 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3490 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3491 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3492 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3493 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3494 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3495 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3496 PetscFunctionReturn(PETSC_SUCCESS); 3497 } 3498 3499 /*@ 3500 MatQRFactor - Performs in-place QR factorization of matrix. 3501 3502 Collective 3503 3504 Input Parameters: 3505 + mat - the matrix 3506 . col - column permutation 3507 - info - options for factorization, includes 3508 .vb 3509 fill - expected fill as ratio of original fill. 3510 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3511 Run with the option -info to determine an optimal value to use 3512 .ve 3513 3514 Level: developer 3515 3516 Notes: 3517 Most users should employ the `KSP` interface for linear solvers 3518 instead of working directly with matrix algebra routines such as this. 3519 See, e.g., `KSPCreate()`. 3520 3521 This changes the state of the matrix to a factored matrix; it cannot be used 3522 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3523 3524 Developer Note: 3525 The Fortran interface is not autogenerated as the 3526 interface definition cannot be generated correctly [due to MatFactorInfo] 3527 3528 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3529 `MatSetUnfactored()` 3530 @*/ 3531 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3532 { 3533 PetscFunctionBegin; 3534 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3535 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3536 if (info) PetscAssertPointer(info, 3); 3537 PetscValidType(mat, 1); 3538 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3539 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3540 MatCheckPreallocated(mat, 1); 3541 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3542 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3543 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3544 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3545 PetscFunctionReturn(PETSC_SUCCESS); 3546 } 3547 3548 /*@ 3549 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3550 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3551 3552 Collective 3553 3554 Input Parameters: 3555 + fact - the factor matrix obtained with `MatGetFactor()` 3556 . mat - the matrix 3557 . col - column permutation 3558 - info - options for factorization, includes 3559 .vb 3560 fill - expected fill as ratio of original fill. 3561 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3562 Run with the option -info to determine an optimal value to use 3563 .ve 3564 3565 Level: developer 3566 3567 Note: 3568 Most users should employ the `KSP` interface for linear solvers 3569 instead of working directly with matrix algebra routines such as this. 3570 See, e.g., `KSPCreate()`. 3571 3572 Developer Note: 3573 The Fortran interface is not autogenerated as the 3574 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3575 3576 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3577 @*/ 3578 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3579 { 3580 MatFactorInfo tinfo; 3581 3582 PetscFunctionBegin; 3583 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3584 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3585 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3586 if (info) PetscAssertPointer(info, 4); 3587 PetscValidType(fact, 1); 3588 PetscValidType(mat, 2); 3589 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3590 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3591 MatCheckPreallocated(mat, 2); 3592 if (!info) { 3593 PetscCall(MatFactorInfoInitialize(&tinfo)); 3594 info = &tinfo; 3595 } 3596 3597 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3598 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3599 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3600 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3601 PetscFunctionReturn(PETSC_SUCCESS); 3602 } 3603 3604 /*@ 3605 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3606 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3607 3608 Collective 3609 3610 Input Parameters: 3611 + fact - the factor matrix obtained with `MatGetFactor()` 3612 . mat - the matrix 3613 - info - options for factorization 3614 3615 Level: developer 3616 3617 Notes: 3618 See `MatQRFactor()` for in-place factorization. 3619 3620 Most users should employ the `KSP` interface for linear solvers 3621 instead of working directly with matrix algebra routines such as this. 3622 See, e.g., `KSPCreate()`. 3623 3624 Developer Note: 3625 The Fortran interface is not autogenerated as the 3626 interface definition cannot be generated correctly [due to `MatFactorInfo`] 3627 3628 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3629 @*/ 3630 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3631 { 3632 MatFactorInfo tinfo; 3633 3634 PetscFunctionBegin; 3635 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3637 PetscValidType(fact, 1); 3638 PetscValidType(mat, 2); 3639 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3640 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, 3641 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3642 3643 MatCheckPreallocated(mat, 2); 3644 if (!info) { 3645 PetscCall(MatFactorInfoInitialize(&tinfo)); 3646 info = &tinfo; 3647 } 3648 3649 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3650 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3651 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3652 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3653 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3654 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3655 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3656 PetscFunctionReturn(PETSC_SUCCESS); 3657 } 3658 3659 /*@ 3660 MatSolve - Solves $A x = b$, given a factored matrix. 3661 3662 Neighbor-wise Collective 3663 3664 Input Parameters: 3665 + mat - the factored matrix 3666 - b - the right-hand-side vector 3667 3668 Output Parameter: 3669 . x - the result vector 3670 3671 Level: developer 3672 3673 Notes: 3674 The vectors `b` and `x` cannot be the same. I.e., one cannot 3675 call `MatSolve`(A,x,x). 3676 3677 Most users should employ the `KSP` interface for linear solvers 3678 instead of working directly with matrix algebra routines such as this. 3679 See, e.g., `KSPCreate()`. 3680 3681 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3682 @*/ 3683 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3684 { 3685 PetscFunctionBegin; 3686 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3687 PetscValidType(mat, 1); 3688 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3689 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3690 PetscCheckSameComm(mat, 1, b, 2); 3691 PetscCheckSameComm(mat, 1, x, 3); 3692 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3693 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); 3694 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); 3695 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); 3696 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3697 MatCheckPreallocated(mat, 1); 3698 3699 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3700 PetscCall(VecFlag(x, mat->factorerrortype)); 3701 if (mat->factorerrortype) { 3702 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3703 } else PetscUseTypeMethod(mat, solve, b, x); 3704 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3705 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3706 PetscFunctionReturn(PETSC_SUCCESS); 3707 } 3708 3709 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3710 { 3711 Vec b, x; 3712 PetscInt N, i; 3713 PetscErrorCode (*f)(Mat, Vec, Vec); 3714 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3715 3716 PetscFunctionBegin; 3717 if (A->factorerrortype) { 3718 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3719 PetscCall(MatSetInf(X)); 3720 PetscFunctionReturn(PETSC_SUCCESS); 3721 } 3722 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3723 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3724 PetscCall(MatBoundToCPU(A, &Abound)); 3725 if (!Abound) { 3726 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3727 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3728 } 3729 #if PetscDefined(HAVE_CUDA) 3730 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3731 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3732 #elif PetscDefined(HAVE_HIP) 3733 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3734 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3735 #endif 3736 PetscCall(MatGetSize(B, NULL, &N)); 3737 for (i = 0; i < N; i++) { 3738 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3739 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3740 PetscCall((*f)(A, b, x)); 3741 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3742 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3743 } 3744 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3745 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3746 PetscFunctionReturn(PETSC_SUCCESS); 3747 } 3748 3749 /*@ 3750 MatMatSolve - Solves $A X = B$, given a factored matrix. 3751 3752 Neighbor-wise Collective 3753 3754 Input Parameters: 3755 + A - the factored matrix 3756 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3757 3758 Output Parameter: 3759 . X - the result matrix (dense matrix) 3760 3761 Level: developer 3762 3763 Note: 3764 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3765 otherwise, `B` and `X` cannot be the same. 3766 3767 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3768 @*/ 3769 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3770 { 3771 PetscFunctionBegin; 3772 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3773 PetscValidType(A, 1); 3774 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3775 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3776 PetscCheckSameComm(A, 1, B, 2); 3777 PetscCheckSameComm(A, 1, X, 3); 3778 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); 3779 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); 3780 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"); 3781 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3782 MatCheckPreallocated(A, 1); 3783 3784 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3785 if (!A->ops->matsolve) { 3786 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3787 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3788 } else PetscUseTypeMethod(A, matsolve, B, X); 3789 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3790 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3791 PetscFunctionReturn(PETSC_SUCCESS); 3792 } 3793 3794 /*@ 3795 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3796 3797 Neighbor-wise Collective 3798 3799 Input Parameters: 3800 + A - the factored matrix 3801 - B - the right-hand-side matrix (`MATDENSE` matrix) 3802 3803 Output Parameter: 3804 . X - the result matrix (dense matrix) 3805 3806 Level: developer 3807 3808 Note: 3809 The matrices `B` and `X` cannot be the same. I.e., one cannot 3810 call `MatMatSolveTranspose`(A,X,X). 3811 3812 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3813 @*/ 3814 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3815 { 3816 PetscFunctionBegin; 3817 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3818 PetscValidType(A, 1); 3819 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3820 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3821 PetscCheckSameComm(A, 1, B, 2); 3822 PetscCheckSameComm(A, 1, X, 3); 3823 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3824 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); 3825 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); 3826 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); 3827 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"); 3828 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3829 MatCheckPreallocated(A, 1); 3830 3831 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3832 if (!A->ops->matsolvetranspose) { 3833 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3834 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3835 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3836 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3837 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3838 PetscFunctionReturn(PETSC_SUCCESS); 3839 } 3840 3841 /*@ 3842 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3843 3844 Neighbor-wise Collective 3845 3846 Input Parameters: 3847 + A - the factored matrix 3848 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3849 3850 Output Parameter: 3851 . X - the result matrix (dense matrix) 3852 3853 Level: developer 3854 3855 Note: 3856 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 3857 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3858 3859 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3860 @*/ 3861 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3862 { 3863 PetscFunctionBegin; 3864 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3865 PetscValidType(A, 1); 3866 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3867 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3868 PetscCheckSameComm(A, 1, Bt, 2); 3869 PetscCheckSameComm(A, 1, X, 3); 3870 3871 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3872 PetscCheck(A->cmap->N == X->rmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat X: global dim %" PetscInt_FMT " %" PetscInt_FMT, A->cmap->N, X->rmap->N); 3873 PetscCheck(A->rmap->N == 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); 3874 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"); 3875 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3876 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3877 MatCheckPreallocated(A, 1); 3878 3879 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3880 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3881 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3882 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3883 PetscFunctionReturn(PETSC_SUCCESS); 3884 } 3885 3886 /*@ 3887 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3888 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3889 3890 Neighbor-wise Collective 3891 3892 Input Parameters: 3893 + mat - the factored matrix 3894 - b - the right-hand-side vector 3895 3896 Output Parameter: 3897 . x - the result vector 3898 3899 Level: developer 3900 3901 Notes: 3902 `MatSolve()` should be used for most applications, as it performs 3903 a forward solve followed by a backward solve. 3904 3905 The vectors `b` and `x` cannot be the same, i.e., one cannot 3906 call `MatForwardSolve`(A,x,x). 3907 3908 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3909 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3910 `MatForwardSolve()` solves $U^T*D y = b$, and 3911 `MatBackwardSolve()` solves $U x = y$. 3912 Thus they do not provide a symmetric preconditioner. 3913 3914 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3915 @*/ 3916 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3917 { 3918 PetscFunctionBegin; 3919 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3920 PetscValidType(mat, 1); 3921 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3922 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3923 PetscCheckSameComm(mat, 1, b, 2); 3924 PetscCheckSameComm(mat, 1, x, 3); 3925 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3926 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); 3927 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); 3928 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); 3929 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3930 MatCheckPreallocated(mat, 1); 3931 3932 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3933 PetscUseTypeMethod(mat, forwardsolve, b, x); 3934 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3935 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3936 PetscFunctionReturn(PETSC_SUCCESS); 3937 } 3938 3939 /*@ 3940 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3941 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3942 3943 Neighbor-wise Collective 3944 3945 Input Parameters: 3946 + mat - the factored matrix 3947 - b - the right-hand-side vector 3948 3949 Output Parameter: 3950 . x - the result vector 3951 3952 Level: developer 3953 3954 Notes: 3955 `MatSolve()` should be used for most applications, as it performs 3956 a forward solve followed by a backward solve. 3957 3958 The vectors `b` and `x` cannot be the same. I.e., one cannot 3959 call `MatBackwardSolve`(A,x,x). 3960 3961 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3962 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3963 `MatForwardSolve()` solves $U^T*D y = b$, and 3964 `MatBackwardSolve()` solves $U x = y$. 3965 Thus they do not provide a symmetric preconditioner. 3966 3967 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3968 @*/ 3969 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3970 { 3971 PetscFunctionBegin; 3972 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3973 PetscValidType(mat, 1); 3974 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3975 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3976 PetscCheckSameComm(mat, 1, b, 2); 3977 PetscCheckSameComm(mat, 1, x, 3); 3978 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3979 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); 3980 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); 3981 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); 3982 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3983 MatCheckPreallocated(mat, 1); 3984 3985 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3986 PetscUseTypeMethod(mat, backwardsolve, b, x); 3987 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3988 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3989 PetscFunctionReturn(PETSC_SUCCESS); 3990 } 3991 3992 /*@ 3993 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3994 3995 Neighbor-wise Collective 3996 3997 Input Parameters: 3998 + mat - the factored matrix 3999 . b - the right-hand-side vector 4000 - y - the vector to be added to 4001 4002 Output Parameter: 4003 . x - the result vector 4004 4005 Level: developer 4006 4007 Note: 4008 The vectors `b` and `x` cannot be the same. I.e., one cannot 4009 call `MatSolveAdd`(A,x,y,x). 4010 4011 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 4012 @*/ 4013 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 4014 { 4015 PetscScalar one = 1.0; 4016 Vec tmp; 4017 4018 PetscFunctionBegin; 4019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4020 PetscValidType(mat, 1); 4021 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4022 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4023 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4024 PetscCheckSameComm(mat, 1, b, 2); 4025 PetscCheckSameComm(mat, 1, y, 3); 4026 PetscCheckSameComm(mat, 1, x, 4); 4027 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4028 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); 4029 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); 4030 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); 4031 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); 4032 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); 4033 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4034 MatCheckPreallocated(mat, 1); 4035 4036 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4037 PetscCall(VecFlag(x, mat->factorerrortype)); 4038 if (mat->factorerrortype) { 4039 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4040 } else if (mat->ops->solveadd) { 4041 PetscUseTypeMethod(mat, solveadd, b, y, x); 4042 } else { 4043 /* do the solve then the add manually */ 4044 if (x != y) { 4045 PetscCall(MatSolve(mat, b, x)); 4046 PetscCall(VecAXPY(x, one, y)); 4047 } else { 4048 PetscCall(VecDuplicate(x, &tmp)); 4049 PetscCall(VecCopy(x, tmp)); 4050 PetscCall(MatSolve(mat, b, x)); 4051 PetscCall(VecAXPY(x, one, tmp)); 4052 PetscCall(VecDestroy(&tmp)); 4053 } 4054 } 4055 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4056 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4057 PetscFunctionReturn(PETSC_SUCCESS); 4058 } 4059 4060 /*@ 4061 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4062 4063 Neighbor-wise Collective 4064 4065 Input Parameters: 4066 + mat - the factored matrix 4067 - b - the right-hand-side vector 4068 4069 Output Parameter: 4070 . x - the result vector 4071 4072 Level: developer 4073 4074 Notes: 4075 The vectors `b` and `x` cannot be the same. I.e., one cannot 4076 call `MatSolveTranspose`(A,x,x). 4077 4078 Most users should employ the `KSP` interface for linear solvers 4079 instead of working directly with matrix algebra routines such as this. 4080 See, e.g., `KSPCreate()`. 4081 4082 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4083 @*/ 4084 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4085 { 4086 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4087 4088 PetscFunctionBegin; 4089 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4090 PetscValidType(mat, 1); 4091 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4092 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4093 PetscCheckSameComm(mat, 1, b, 2); 4094 PetscCheckSameComm(mat, 1, x, 3); 4095 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4096 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); 4097 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); 4098 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4099 MatCheckPreallocated(mat, 1); 4100 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4101 PetscCall(VecFlag(x, mat->factorerrortype)); 4102 if (mat->factorerrortype) { 4103 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4104 } else { 4105 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4106 PetscCall((*f)(mat, b, x)); 4107 } 4108 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4109 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4110 PetscFunctionReturn(PETSC_SUCCESS); 4111 } 4112 4113 /*@ 4114 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4115 factored matrix. 4116 4117 Neighbor-wise Collective 4118 4119 Input Parameters: 4120 + mat - the factored matrix 4121 . b - the right-hand-side vector 4122 - y - the vector to be added to 4123 4124 Output Parameter: 4125 . x - the result vector 4126 4127 Level: developer 4128 4129 Note: 4130 The vectors `b` and `x` cannot be the same. I.e., one cannot 4131 call `MatSolveTransposeAdd`(A,x,y,x). 4132 4133 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4134 @*/ 4135 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4136 { 4137 PetscScalar one = 1.0; 4138 Vec tmp; 4139 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4140 4141 PetscFunctionBegin; 4142 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4143 PetscValidType(mat, 1); 4144 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4145 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4146 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4147 PetscCheckSameComm(mat, 1, b, 2); 4148 PetscCheckSameComm(mat, 1, y, 3); 4149 PetscCheckSameComm(mat, 1, x, 4); 4150 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4151 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); 4152 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); 4153 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); 4154 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); 4155 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4156 MatCheckPreallocated(mat, 1); 4157 4158 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4159 PetscCall(VecFlag(x, mat->factorerrortype)); 4160 if (mat->factorerrortype) { 4161 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4162 } else if (f) { 4163 PetscCall((*f)(mat, b, y, x)); 4164 } else { 4165 /* do the solve then the add manually */ 4166 if (x != y) { 4167 PetscCall(MatSolveTranspose(mat, b, x)); 4168 PetscCall(VecAXPY(x, one, y)); 4169 } else { 4170 PetscCall(VecDuplicate(x, &tmp)); 4171 PetscCall(VecCopy(x, tmp)); 4172 PetscCall(MatSolveTranspose(mat, b, x)); 4173 PetscCall(VecAXPY(x, one, tmp)); 4174 PetscCall(VecDestroy(&tmp)); 4175 } 4176 } 4177 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4178 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4179 PetscFunctionReturn(PETSC_SUCCESS); 4180 } 4181 4182 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4183 /*@ 4184 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4185 4186 Neighbor-wise Collective 4187 4188 Input Parameters: 4189 + mat - the matrix 4190 . b - the right-hand side 4191 . omega - the relaxation factor 4192 . flag - flag indicating the type of SOR (see below) 4193 . shift - diagonal shift 4194 . its - the number of iterations 4195 - lits - the number of local iterations 4196 4197 Output Parameter: 4198 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4199 4200 SOR Flags: 4201 + `SOR_FORWARD_SWEEP` - forward SOR 4202 . `SOR_BACKWARD_SWEEP` - backward SOR 4203 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4204 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4205 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4206 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4207 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4208 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies 4209 upper/lower triangular part of matrix to 4210 vector (with omega) 4211 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4212 4213 Level: developer 4214 4215 Notes: 4216 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4217 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4218 on each processor. 4219 4220 Application programmers will not generally use `MatSOR()` directly, 4221 but instead will employ the `KSP`/`PC` interface. 4222 4223 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing 4224 4225 Most users should employ the `KSP` interface for linear solvers 4226 instead of working directly with matrix algebra routines such as this. 4227 See, e.g., `KSPCreate()`. 4228 4229 Vectors `x` and `b` CANNOT be the same 4230 4231 The flags are implemented as bitwise inclusive or operations. 4232 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4233 to specify a zero initial guess for SSOR. 4234 4235 Developer Note: 4236 We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes 4237 4238 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4239 @*/ 4240 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4241 { 4242 PetscFunctionBegin; 4243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4244 PetscValidType(mat, 1); 4245 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4246 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4247 PetscCheckSameComm(mat, 1, b, 2); 4248 PetscCheckSameComm(mat, 1, x, 8); 4249 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4250 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4251 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); 4252 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); 4253 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); 4254 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4255 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4256 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4257 4258 MatCheckPreallocated(mat, 1); 4259 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4260 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4261 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4262 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4263 PetscFunctionReturn(PETSC_SUCCESS); 4264 } 4265 4266 /* 4267 Default matrix copy routine. 4268 */ 4269 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4270 { 4271 PetscInt i, rstart = 0, rend = 0, nz; 4272 const PetscInt *cwork; 4273 const PetscScalar *vwork; 4274 4275 PetscFunctionBegin; 4276 if (B->assembled) PetscCall(MatZeroEntries(B)); 4277 if (str == SAME_NONZERO_PATTERN) { 4278 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4279 for (i = rstart; i < rend; i++) { 4280 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4281 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4282 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4283 } 4284 } else { 4285 PetscCall(MatAYPX(B, 0.0, A, str)); 4286 } 4287 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4288 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4289 PetscFunctionReturn(PETSC_SUCCESS); 4290 } 4291 4292 /*@ 4293 MatCopy - Copies a matrix to another matrix. 4294 4295 Collective 4296 4297 Input Parameters: 4298 + A - the matrix 4299 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4300 4301 Output Parameter: 4302 . B - where the copy is put 4303 4304 Level: intermediate 4305 4306 Notes: 4307 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4308 4309 `MatCopy()` copies the matrix entries of a matrix to another existing 4310 matrix (after first zeroing the second matrix). A related routine is 4311 `MatConvert()`, which first creates a new matrix and then copies the data. 4312 4313 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4314 @*/ 4315 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4316 { 4317 PetscInt i; 4318 4319 PetscFunctionBegin; 4320 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4321 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4322 PetscValidType(A, 1); 4323 PetscValidType(B, 2); 4324 PetscCheckSameComm(A, 1, B, 2); 4325 MatCheckPreallocated(B, 2); 4326 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4327 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4328 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, 4329 A->cmap->N, B->cmap->N); 4330 MatCheckPreallocated(A, 1); 4331 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4332 4333 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4334 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4335 else PetscCall(MatCopy_Basic(A, B, str)); 4336 4337 B->stencil.dim = A->stencil.dim; 4338 B->stencil.noc = A->stencil.noc; 4339 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4340 B->stencil.dims[i] = A->stencil.dims[i]; 4341 B->stencil.starts[i] = A->stencil.starts[i]; 4342 } 4343 4344 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4345 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4346 PetscFunctionReturn(PETSC_SUCCESS); 4347 } 4348 4349 /*@ 4350 MatConvert - Converts a matrix to another matrix, either of the same 4351 or different type. 4352 4353 Collective 4354 4355 Input Parameters: 4356 + mat - the matrix 4357 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4358 same type as the original matrix. 4359 - reuse - denotes if the destination matrix is to be created or reused. 4360 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 4361 `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). 4362 4363 Output Parameter: 4364 . M - pointer to place new matrix 4365 4366 Level: intermediate 4367 4368 Notes: 4369 `MatConvert()` first creates a new matrix and then copies the data from 4370 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4371 entries of one matrix to another already existing matrix context. 4372 4373 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4374 the MPI communicator of the generated matrix is always the same as the communicator 4375 of the input matrix. 4376 4377 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4378 @*/ 4379 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4380 { 4381 PetscBool sametype, issame, flg; 4382 PetscBool3 issymmetric, ishermitian; 4383 char convname[256], mtype[256]; 4384 Mat B; 4385 4386 PetscFunctionBegin; 4387 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4388 PetscValidType(mat, 1); 4389 PetscAssertPointer(M, 4); 4390 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4391 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4392 MatCheckPreallocated(mat, 1); 4393 4394 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4395 if (flg) newtype = mtype; 4396 4397 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4398 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4399 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4400 if (reuse == MAT_REUSE_MATRIX) { 4401 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4402 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4403 } 4404 4405 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4406 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4407 PetscFunctionReturn(PETSC_SUCCESS); 4408 } 4409 4410 /* Cache Mat options because some converters use MatHeaderReplace */ 4411 issymmetric = mat->symmetric; 4412 ishermitian = mat->hermitian; 4413 4414 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4415 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4416 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4417 } else { 4418 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4419 const char *prefix[3] = {"seq", "mpi", ""}; 4420 PetscInt i; 4421 /* 4422 Order of precedence: 4423 0) See if newtype is a superclass of the current matrix. 4424 1) See if a specialized converter is known to the current matrix. 4425 2) See if a specialized converter is known to the desired matrix class. 4426 3) See if a good general converter is registered for the desired class 4427 (as of 6/27/03 only MATMPIADJ falls into this category). 4428 4) See if a good general converter is known for the current matrix. 4429 5) Use a really basic converter. 4430 */ 4431 4432 /* 0) See if newtype is a superclass of the current matrix. 4433 i.e mat is mpiaij and newtype is aij */ 4434 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4435 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4436 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4437 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4438 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4439 if (flg) { 4440 if (reuse == MAT_INPLACE_MATRIX) { 4441 PetscCall(PetscInfo(mat, "Early return\n")); 4442 PetscFunctionReturn(PETSC_SUCCESS); 4443 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4444 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4445 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4446 PetscFunctionReturn(PETSC_SUCCESS); 4447 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4448 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4449 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4450 PetscFunctionReturn(PETSC_SUCCESS); 4451 } 4452 } 4453 } 4454 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4455 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4456 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4457 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4458 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4459 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4460 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4461 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4462 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4463 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4464 if (conv) goto foundconv; 4465 } 4466 4467 /* 2) See if a specialized converter is known to the desired matrix class. */ 4468 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4469 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4470 PetscCall(MatSetType(B, newtype)); 4471 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4472 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4473 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4474 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4475 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4476 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4477 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4478 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4479 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4480 if (conv) { 4481 PetscCall(MatDestroy(&B)); 4482 goto foundconv; 4483 } 4484 } 4485 4486 /* 3) See if a good general converter is registered for the desired class */ 4487 conv = B->ops->convertfrom; 4488 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4489 PetscCall(MatDestroy(&B)); 4490 if (conv) goto foundconv; 4491 4492 /* 4) See if a good general converter is known for the current matrix */ 4493 if (mat->ops->convert) conv = mat->ops->convert; 4494 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4495 if (conv) goto foundconv; 4496 4497 /* 5) Use a really basic converter. */ 4498 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4499 conv = MatConvert_Basic; 4500 4501 foundconv: 4502 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4503 PetscCall((*conv)(mat, newtype, reuse, M)); 4504 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4505 /* the block sizes must be same if the mappings are copied over */ 4506 (*M)->rmap->bs = mat->rmap->bs; 4507 (*M)->cmap->bs = mat->cmap->bs; 4508 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4509 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4510 (*M)->rmap->mapping = mat->rmap->mapping; 4511 (*M)->cmap->mapping = mat->cmap->mapping; 4512 } 4513 (*M)->stencil.dim = mat->stencil.dim; 4514 (*M)->stencil.noc = mat->stencil.noc; 4515 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4516 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4517 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4518 } 4519 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4520 } 4521 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4522 4523 /* Copy Mat options */ 4524 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4525 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4526 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4527 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 4528 PetscFunctionReturn(PETSC_SUCCESS); 4529 } 4530 4531 /*@ 4532 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4533 4534 Not Collective 4535 4536 Input Parameter: 4537 . mat - the matrix, must be a factored matrix 4538 4539 Output Parameter: 4540 . type - the string name of the package (do not free this string) 4541 4542 Level: intermediate 4543 4544 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4545 @*/ 4546 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4547 { 4548 PetscErrorCode (*conv)(Mat, MatSolverType *); 4549 4550 PetscFunctionBegin; 4551 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4552 PetscValidType(mat, 1); 4553 PetscAssertPointer(type, 2); 4554 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4555 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4556 if (conv) PetscCall((*conv)(mat, type)); 4557 else *type = MATSOLVERPETSC; 4558 PetscFunctionReturn(PETSC_SUCCESS); 4559 } 4560 4561 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4562 struct _MatSolverTypeForSpecifcType { 4563 MatType mtype; 4564 /* no entry for MAT_FACTOR_NONE */ 4565 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4566 MatSolverTypeForSpecifcType next; 4567 }; 4568 4569 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4570 struct _MatSolverTypeHolder { 4571 char *name; 4572 MatSolverTypeForSpecifcType handlers; 4573 MatSolverTypeHolder next; 4574 }; 4575 4576 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4577 4578 /*@C 4579 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4580 4581 Logically Collective, No Fortran Support 4582 4583 Input Parameters: 4584 + package - name of the package, for example `petsc` or `superlu` 4585 . mtype - the matrix type that works with this package 4586 . ftype - the type of factorization supported by the package 4587 - createfactor - routine that will create the factored matrix ready to be used 4588 4589 Level: developer 4590 4591 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4592 `MatGetFactor()` 4593 @*/ 4594 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4595 { 4596 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4597 PetscBool flg; 4598 MatSolverTypeForSpecifcType inext, iprev = NULL; 4599 4600 PetscFunctionBegin; 4601 PetscCall(MatInitializePackage()); 4602 if (!next) { 4603 PetscCall(PetscNew(&MatSolverTypeHolders)); 4604 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4605 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4606 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4607 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4608 PetscFunctionReturn(PETSC_SUCCESS); 4609 } 4610 while (next) { 4611 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4612 if (flg) { 4613 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4614 inext = next->handlers; 4615 while (inext) { 4616 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4617 if (flg) { 4618 inext->createfactor[(int)ftype - 1] = createfactor; 4619 PetscFunctionReturn(PETSC_SUCCESS); 4620 } 4621 iprev = inext; 4622 inext = inext->next; 4623 } 4624 PetscCall(PetscNew(&iprev->next)); 4625 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4626 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4627 PetscFunctionReturn(PETSC_SUCCESS); 4628 } 4629 prev = next; 4630 next = next->next; 4631 } 4632 PetscCall(PetscNew(&prev->next)); 4633 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4634 PetscCall(PetscNew(&prev->next->handlers)); 4635 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4636 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4637 PetscFunctionReturn(PETSC_SUCCESS); 4638 } 4639 4640 /*@C 4641 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4642 4643 Input Parameters: 4644 + 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 4645 . ftype - the type of factorization supported by the type 4646 - mtype - the matrix type that works with this type 4647 4648 Output Parameters: 4649 + foundtype - `PETSC_TRUE` if the type was registered 4650 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4651 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4652 4653 Calling sequence of `createfactor`: 4654 + A - the matrix providing the factor matrix 4655 . ftype - the `MatFactorType` of the factor requested 4656 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4657 4658 Level: developer 4659 4660 Note: 4661 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4662 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4663 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4664 4665 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4666 `MatInitializePackage()` 4667 @*/ 4668 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4669 { 4670 MatSolverTypeHolder next = MatSolverTypeHolders; 4671 PetscBool flg; 4672 MatSolverTypeForSpecifcType inext; 4673 4674 PetscFunctionBegin; 4675 if (foundtype) *foundtype = PETSC_FALSE; 4676 if (foundmtype) *foundmtype = PETSC_FALSE; 4677 if (createfactor) *createfactor = NULL; 4678 4679 if (type) { 4680 while (next) { 4681 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4682 if (flg) { 4683 if (foundtype) *foundtype = PETSC_TRUE; 4684 inext = next->handlers; 4685 while (inext) { 4686 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4687 if (flg) { 4688 if (foundmtype) *foundmtype = PETSC_TRUE; 4689 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4690 PetscFunctionReturn(PETSC_SUCCESS); 4691 } 4692 inext = inext->next; 4693 } 4694 } 4695 next = next->next; 4696 } 4697 } else { 4698 while (next) { 4699 inext = next->handlers; 4700 while (inext) { 4701 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4702 if (flg && inext->createfactor[(int)ftype - 1]) { 4703 if (foundtype) *foundtype = PETSC_TRUE; 4704 if (foundmtype) *foundmtype = PETSC_TRUE; 4705 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4706 PetscFunctionReturn(PETSC_SUCCESS); 4707 } 4708 inext = inext->next; 4709 } 4710 next = next->next; 4711 } 4712 /* try with base classes inext->mtype */ 4713 next = MatSolverTypeHolders; 4714 while (next) { 4715 inext = next->handlers; 4716 while (inext) { 4717 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4718 if (flg && inext->createfactor[(int)ftype - 1]) { 4719 if (foundtype) *foundtype = PETSC_TRUE; 4720 if (foundmtype) *foundmtype = PETSC_TRUE; 4721 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4722 PetscFunctionReturn(PETSC_SUCCESS); 4723 } 4724 inext = inext->next; 4725 } 4726 next = next->next; 4727 } 4728 } 4729 PetscFunctionReturn(PETSC_SUCCESS); 4730 } 4731 4732 PetscErrorCode MatSolverTypeDestroy(void) 4733 { 4734 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4735 MatSolverTypeForSpecifcType inext, iprev; 4736 4737 PetscFunctionBegin; 4738 while (next) { 4739 PetscCall(PetscFree(next->name)); 4740 inext = next->handlers; 4741 while (inext) { 4742 PetscCall(PetscFree(inext->mtype)); 4743 iprev = inext; 4744 inext = inext->next; 4745 PetscCall(PetscFree(iprev)); 4746 } 4747 prev = next; 4748 next = next->next; 4749 PetscCall(PetscFree(prev)); 4750 } 4751 MatSolverTypeHolders = NULL; 4752 PetscFunctionReturn(PETSC_SUCCESS); 4753 } 4754 4755 /*@ 4756 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4757 4758 Logically Collective 4759 4760 Input Parameter: 4761 . mat - the matrix 4762 4763 Output Parameter: 4764 . flg - `PETSC_TRUE` if uses the ordering 4765 4766 Level: developer 4767 4768 Note: 4769 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4770 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4771 4772 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4773 @*/ 4774 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4775 { 4776 PetscFunctionBegin; 4777 *flg = mat->canuseordering; 4778 PetscFunctionReturn(PETSC_SUCCESS); 4779 } 4780 4781 /*@ 4782 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4783 4784 Logically Collective 4785 4786 Input Parameters: 4787 + mat - the matrix obtained with `MatGetFactor()` 4788 - ftype - the factorization type to be used 4789 4790 Output Parameter: 4791 . otype - the preferred ordering type 4792 4793 Level: developer 4794 4795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4796 @*/ 4797 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4798 { 4799 PetscFunctionBegin; 4800 *otype = mat->preferredordering[ftype]; 4801 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4802 PetscFunctionReturn(PETSC_SUCCESS); 4803 } 4804 4805 /*@ 4806 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4807 4808 Collective 4809 4810 Input Parameters: 4811 + mat - the matrix 4812 . 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 4813 the other criteria is returned 4814 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4815 4816 Output Parameter: 4817 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4818 4819 Options Database Keys: 4820 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4821 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4822 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4823 4824 Level: intermediate 4825 4826 Notes: 4827 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4828 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4829 4830 Users usually access the factorization solvers via `KSP` 4831 4832 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4833 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 4834 4835 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4836 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4837 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4838 4839 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4840 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4841 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4842 4843 Developer Note: 4844 This should actually be called `MatCreateFactor()` since it creates a new factor object 4845 4846 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4847 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4848 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4849 @*/ 4850 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4851 { 4852 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4853 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4854 4855 PetscFunctionBegin; 4856 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4857 PetscValidType(mat, 1); 4858 4859 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4860 MatCheckPreallocated(mat, 1); 4861 4862 PetscCall(MatIsShell(mat, &shell)); 4863 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4864 if (hasop) { 4865 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4866 PetscFunctionReturn(PETSC_SUCCESS); 4867 } 4868 4869 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4870 if (!foundtype) { 4871 if (type) { 4872 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], 4873 ((PetscObject)mat)->type_name, type); 4874 } else { 4875 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); 4876 } 4877 } 4878 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4879 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); 4880 4881 PetscCall((*conv)(mat, ftype, f)); 4882 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4883 PetscFunctionReturn(PETSC_SUCCESS); 4884 } 4885 4886 /*@ 4887 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4888 4889 Not Collective 4890 4891 Input Parameters: 4892 + mat - the matrix 4893 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4894 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4895 4896 Output Parameter: 4897 . flg - PETSC_TRUE if the factorization is available 4898 4899 Level: intermediate 4900 4901 Notes: 4902 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4903 such as pastix, superlu, mumps etc. 4904 4905 PETSc must have been ./configure to use the external solver, using the option --download-package 4906 4907 Developer Note: 4908 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4909 4910 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4911 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4912 @*/ 4913 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4914 { 4915 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4916 4917 PetscFunctionBegin; 4918 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4919 PetscAssertPointer(flg, 4); 4920 4921 *flg = PETSC_FALSE; 4922 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4923 4924 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4925 MatCheckPreallocated(mat, 1); 4926 4927 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4928 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4929 PetscFunctionReturn(PETSC_SUCCESS); 4930 } 4931 4932 /*@ 4933 MatDuplicate - Duplicates a matrix including the non-zero structure. 4934 4935 Collective 4936 4937 Input Parameters: 4938 + mat - the matrix 4939 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4940 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4941 4942 Output Parameter: 4943 . M - pointer to place new matrix 4944 4945 Level: intermediate 4946 4947 Notes: 4948 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4949 4950 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4951 4952 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. 4953 4954 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4955 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4956 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4957 4958 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4959 @*/ 4960 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4961 { 4962 Mat B; 4963 VecType vtype; 4964 PetscInt i; 4965 PetscObject dm, container_h, container_d; 4966 void (*viewf)(void); 4967 4968 PetscFunctionBegin; 4969 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4970 PetscValidType(mat, 1); 4971 PetscAssertPointer(M, 3); 4972 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4973 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4974 MatCheckPreallocated(mat, 1); 4975 4976 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4977 PetscUseTypeMethod(mat, duplicate, op, M); 4978 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4979 B = *M; 4980 4981 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4982 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4983 PetscCall(MatGetVecType(mat, &vtype)); 4984 PetscCall(MatSetVecType(B, vtype)); 4985 4986 B->stencil.dim = mat->stencil.dim; 4987 B->stencil.noc = mat->stencil.noc; 4988 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4989 B->stencil.dims[i] = mat->stencil.dims[i]; 4990 B->stencil.starts[i] = mat->stencil.starts[i]; 4991 } 4992 4993 B->nooffproczerorows = mat->nooffproczerorows; 4994 B->nooffprocentries = mat->nooffprocentries; 4995 4996 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4997 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4998 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4999 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 5000 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 5001 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 5002 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 5003 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 5004 PetscFunctionReturn(PETSC_SUCCESS); 5005 } 5006 5007 /*@ 5008 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 5009 5010 Logically Collective 5011 5012 Input Parameter: 5013 . mat - the matrix 5014 5015 Output Parameter: 5016 . v - the diagonal of the matrix 5017 5018 Level: intermediate 5019 5020 Note: 5021 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 5022 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 5023 is larger than `ndiag`, the values of the remaining entries are unspecified. 5024 5025 Currently only correct in parallel for square matrices. 5026 5027 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 5028 @*/ 5029 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 5030 { 5031 PetscFunctionBegin; 5032 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5033 PetscValidType(mat, 1); 5034 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5035 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5036 MatCheckPreallocated(mat, 1); 5037 if (PetscDefined(USE_DEBUG)) { 5038 PetscInt nv, row, col, ndiag; 5039 5040 PetscCall(VecGetLocalSize(v, &nv)); 5041 PetscCall(MatGetLocalSize(mat, &row, &col)); 5042 ndiag = PetscMin(row, col); 5043 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); 5044 } 5045 5046 PetscUseTypeMethod(mat, getdiagonal, v); 5047 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5048 PetscFunctionReturn(PETSC_SUCCESS); 5049 } 5050 5051 /*@ 5052 MatGetRowMin - Gets the minimum value (of the real part) of each 5053 row of the matrix 5054 5055 Logically Collective 5056 5057 Input Parameter: 5058 . mat - the matrix 5059 5060 Output Parameters: 5061 + v - the vector for storing the maximums 5062 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5063 5064 Level: intermediate 5065 5066 Note: 5067 The result of this call are the same as if one converted the matrix to dense format 5068 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5069 5070 This code is only implemented for a couple of matrix formats. 5071 5072 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5073 `MatGetRowMax()` 5074 @*/ 5075 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5076 { 5077 PetscFunctionBegin; 5078 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5079 PetscValidType(mat, 1); 5080 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5081 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5082 5083 if (!mat->cmap->N) { 5084 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5085 if (idx) { 5086 PetscInt i, m = mat->rmap->n; 5087 for (i = 0; i < m; i++) idx[i] = -1; 5088 } 5089 } else { 5090 MatCheckPreallocated(mat, 1); 5091 } 5092 PetscUseTypeMethod(mat, getrowmin, v, idx); 5093 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5094 PetscFunctionReturn(PETSC_SUCCESS); 5095 } 5096 5097 /*@ 5098 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5099 row of the matrix 5100 5101 Logically Collective 5102 5103 Input Parameter: 5104 . mat - the matrix 5105 5106 Output Parameters: 5107 + v - the vector for storing the minimums 5108 - idx - the indices of the column found for each row (or `NULL` if not needed) 5109 5110 Level: intermediate 5111 5112 Notes: 5113 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5114 row is 0 (the first column). 5115 5116 This code is only implemented for a couple of matrix formats. 5117 5118 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5119 @*/ 5120 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5121 { 5122 PetscFunctionBegin; 5123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5124 PetscValidType(mat, 1); 5125 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5126 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5127 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5128 5129 if (!mat->cmap->N) { 5130 PetscCall(VecSet(v, 0.0)); 5131 if (idx) { 5132 PetscInt i, m = mat->rmap->n; 5133 for (i = 0; i < m; i++) idx[i] = -1; 5134 } 5135 } else { 5136 MatCheckPreallocated(mat, 1); 5137 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5138 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5139 } 5140 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5141 PetscFunctionReturn(PETSC_SUCCESS); 5142 } 5143 5144 /*@ 5145 MatGetRowMax - Gets the maximum value (of the real part) of each 5146 row of the matrix 5147 5148 Logically Collective 5149 5150 Input Parameter: 5151 . mat - the matrix 5152 5153 Output Parameters: 5154 + v - the vector for storing the maximums 5155 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5156 5157 Level: intermediate 5158 5159 Notes: 5160 The result of this call are the same as if one converted the matrix to dense format 5161 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5162 5163 This code is only implemented for a couple of matrix formats. 5164 5165 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5166 @*/ 5167 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5168 { 5169 PetscFunctionBegin; 5170 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5171 PetscValidType(mat, 1); 5172 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5173 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5174 5175 if (!mat->cmap->N) { 5176 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5177 if (idx) { 5178 PetscInt i, m = mat->rmap->n; 5179 for (i = 0; i < m; i++) idx[i] = -1; 5180 } 5181 } else { 5182 MatCheckPreallocated(mat, 1); 5183 PetscUseTypeMethod(mat, getrowmax, v, idx); 5184 } 5185 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5186 PetscFunctionReturn(PETSC_SUCCESS); 5187 } 5188 5189 /*@ 5190 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5191 row of the matrix 5192 5193 Logically Collective 5194 5195 Input Parameter: 5196 . mat - the matrix 5197 5198 Output Parameters: 5199 + v - the vector for storing the maximums 5200 - idx - the indices of the column found for each row (or `NULL` if not needed) 5201 5202 Level: intermediate 5203 5204 Notes: 5205 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5206 row is 0 (the first column). 5207 5208 This code is only implemented for a couple of matrix formats. 5209 5210 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5211 @*/ 5212 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5213 { 5214 PetscFunctionBegin; 5215 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5216 PetscValidType(mat, 1); 5217 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5218 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5219 5220 if (!mat->cmap->N) { 5221 PetscCall(VecSet(v, 0.0)); 5222 if (idx) { 5223 PetscInt i, m = mat->rmap->n; 5224 for (i = 0; i < m; i++) idx[i] = -1; 5225 } 5226 } else { 5227 MatCheckPreallocated(mat, 1); 5228 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5229 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5230 } 5231 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5232 PetscFunctionReturn(PETSC_SUCCESS); 5233 } 5234 5235 /*@ 5236 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5237 5238 Logically Collective 5239 5240 Input Parameter: 5241 . mat - the matrix 5242 5243 Output Parameter: 5244 . v - the vector for storing the sum 5245 5246 Level: intermediate 5247 5248 This code is only implemented for a couple of matrix formats. 5249 5250 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5251 @*/ 5252 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5253 { 5254 PetscFunctionBegin; 5255 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5256 PetscValidType(mat, 1); 5257 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5258 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5259 5260 if (!mat->cmap->N) { 5261 PetscCall(VecSet(v, 0.0)); 5262 } else { 5263 MatCheckPreallocated(mat, 1); 5264 PetscUseTypeMethod(mat, getrowsumabs, v); 5265 } 5266 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5267 PetscFunctionReturn(PETSC_SUCCESS); 5268 } 5269 5270 /*@ 5271 MatGetRowSum - Gets the sum of each row of the matrix 5272 5273 Logically or Neighborhood Collective 5274 5275 Input Parameter: 5276 . mat - the matrix 5277 5278 Output Parameter: 5279 . v - the vector for storing the sum of rows 5280 5281 Level: intermediate 5282 5283 Note: 5284 This code is slow since it is not currently specialized for different formats 5285 5286 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5287 @*/ 5288 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5289 { 5290 Vec ones; 5291 5292 PetscFunctionBegin; 5293 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5294 PetscValidType(mat, 1); 5295 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5296 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5297 MatCheckPreallocated(mat, 1); 5298 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5299 PetscCall(VecSet(ones, 1.)); 5300 PetscCall(MatMult(mat, ones, v)); 5301 PetscCall(VecDestroy(&ones)); 5302 PetscFunctionReturn(PETSC_SUCCESS); 5303 } 5304 5305 /*@ 5306 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5307 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5308 5309 Collective 5310 5311 Input Parameter: 5312 . mat - the matrix to provide the transpose 5313 5314 Output Parameter: 5315 . 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 5316 5317 Level: advanced 5318 5319 Note: 5320 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 5321 routine allows bypassing that call. 5322 5323 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5324 @*/ 5325 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5326 { 5327 MatParentState *rb = NULL; 5328 5329 PetscFunctionBegin; 5330 PetscCall(PetscNew(&rb)); 5331 rb->id = ((PetscObject)mat)->id; 5332 rb->state = 0; 5333 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5334 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5335 PetscFunctionReturn(PETSC_SUCCESS); 5336 } 5337 5338 /*@ 5339 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5340 5341 Collective 5342 5343 Input Parameters: 5344 + mat - the matrix to transpose 5345 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5346 5347 Output Parameter: 5348 . B - the transpose of the matrix 5349 5350 Level: intermediate 5351 5352 Notes: 5353 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5354 5355 `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 5356 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5357 5358 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. 5359 5360 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5361 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5362 5363 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5364 5365 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5366 5367 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5368 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5369 @*/ 5370 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5371 { 5372 PetscContainer rB = NULL; 5373 MatParentState *rb = NULL; 5374 5375 PetscFunctionBegin; 5376 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5377 PetscValidType(mat, 1); 5378 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5379 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5380 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5381 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5382 MatCheckPreallocated(mat, 1); 5383 if (reuse == MAT_REUSE_MATRIX) { 5384 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5385 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5386 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5387 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5388 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5389 } 5390 5391 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5392 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5393 PetscUseTypeMethod(mat, transpose, reuse, B); 5394 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5395 } 5396 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5397 5398 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5399 if (reuse != MAT_INPLACE_MATRIX) { 5400 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5401 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5402 rb->state = ((PetscObject)mat)->state; 5403 rb->nonzerostate = mat->nonzerostate; 5404 } 5405 PetscFunctionReturn(PETSC_SUCCESS); 5406 } 5407 5408 /*@ 5409 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5410 5411 Collective 5412 5413 Input Parameter: 5414 . A - the matrix to transpose 5415 5416 Output Parameter: 5417 . 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 5418 numerical portion. 5419 5420 Level: intermediate 5421 5422 Note: 5423 This is not supported for many matrix types, use `MatTranspose()` in those cases 5424 5425 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5426 @*/ 5427 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5428 { 5429 PetscFunctionBegin; 5430 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5431 PetscValidType(A, 1); 5432 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5433 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5434 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5435 PetscUseTypeMethod(A, transposesymbolic, B); 5436 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5437 5438 PetscCall(MatTransposeSetPrecursor(A, *B)); 5439 PetscFunctionReturn(PETSC_SUCCESS); 5440 } 5441 5442 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5443 { 5444 PetscContainer rB; 5445 MatParentState *rb; 5446 5447 PetscFunctionBegin; 5448 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5449 PetscValidType(A, 1); 5450 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5451 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5452 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5453 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5454 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5455 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5456 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5457 PetscFunctionReturn(PETSC_SUCCESS); 5458 } 5459 5460 /*@ 5461 MatIsTranspose - Test whether a matrix is another one's transpose, 5462 or its own, in which case it tests symmetry. 5463 5464 Collective 5465 5466 Input Parameters: 5467 + A - the matrix to test 5468 . B - the matrix to test against, this can equal the first parameter 5469 - tol - tolerance, differences between entries smaller than this are counted as zero 5470 5471 Output Parameter: 5472 . flg - the result 5473 5474 Level: intermediate 5475 5476 Notes: 5477 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5478 test involves parallel copies of the block off-diagonal parts of the matrix. 5479 5480 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5481 @*/ 5482 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5483 { 5484 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5485 5486 PetscFunctionBegin; 5487 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5488 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5489 PetscAssertPointer(flg, 4); 5490 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5491 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5492 *flg = PETSC_FALSE; 5493 if (f && g) { 5494 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5495 PetscCall((*f)(A, B, tol, flg)); 5496 } else { 5497 MatType mattype; 5498 5499 PetscCall(MatGetType(f ? B : A, &mattype)); 5500 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5501 } 5502 PetscFunctionReturn(PETSC_SUCCESS); 5503 } 5504 5505 /*@ 5506 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5507 5508 Collective 5509 5510 Input Parameters: 5511 + mat - the matrix to transpose and complex conjugate 5512 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5513 5514 Output Parameter: 5515 . B - the Hermitian transpose 5516 5517 Level: intermediate 5518 5519 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5520 @*/ 5521 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5522 { 5523 PetscFunctionBegin; 5524 PetscCall(MatTranspose(mat, reuse, B)); 5525 #if defined(PETSC_USE_COMPLEX) 5526 PetscCall(MatConjugate(*B)); 5527 #endif 5528 PetscFunctionReturn(PETSC_SUCCESS); 5529 } 5530 5531 /*@ 5532 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5533 5534 Collective 5535 5536 Input Parameters: 5537 + A - the matrix to test 5538 . B - the matrix to test against, this can equal the first parameter 5539 - tol - tolerance, differences between entries smaller than this are counted as zero 5540 5541 Output Parameter: 5542 . flg - the result 5543 5544 Level: intermediate 5545 5546 Notes: 5547 Only available for `MATAIJ` matrices. 5548 5549 The sequential algorithm 5550 has a running time of the order of the number of nonzeros; the parallel 5551 test involves parallel copies of the block off-diagonal parts of the matrix. 5552 5553 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5554 @*/ 5555 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5556 { 5557 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5558 5559 PetscFunctionBegin; 5560 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5561 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5562 PetscAssertPointer(flg, 4); 5563 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5564 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5565 if (f && g) { 5566 PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5567 PetscCall((*f)(A, B, tol, flg)); 5568 } 5569 PetscFunctionReturn(PETSC_SUCCESS); 5570 } 5571 5572 /*@ 5573 MatPermute - Creates a new matrix with rows and columns permuted from the 5574 original. 5575 5576 Collective 5577 5578 Input Parameters: 5579 + mat - the matrix to permute 5580 . row - row permutation, each processor supplies only the permutation for its rows 5581 - col - column permutation, each processor supplies only the permutation for its columns 5582 5583 Output Parameter: 5584 . B - the permuted matrix 5585 5586 Level: advanced 5587 5588 Note: 5589 The index sets map from row/col of permuted matrix to row/col of original matrix. 5590 The index sets should be on the same communicator as mat and have the same local sizes. 5591 5592 Developer Note: 5593 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5594 exploit the fact that row and col are permutations, consider implementing the 5595 more general `MatCreateSubMatrix()` instead. 5596 5597 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5598 @*/ 5599 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5600 { 5601 PetscFunctionBegin; 5602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5603 PetscValidType(mat, 1); 5604 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5605 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5606 PetscAssertPointer(B, 4); 5607 PetscCheckSameComm(mat, 1, row, 2); 5608 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5609 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5610 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5611 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5612 MatCheckPreallocated(mat, 1); 5613 5614 if (mat->ops->permute) { 5615 PetscUseTypeMethod(mat, permute, row, col, B); 5616 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5617 } else { 5618 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5619 } 5620 PetscFunctionReturn(PETSC_SUCCESS); 5621 } 5622 5623 /*@ 5624 MatEqual - Compares two matrices. 5625 5626 Collective 5627 5628 Input Parameters: 5629 + A - the first matrix 5630 - B - the second matrix 5631 5632 Output Parameter: 5633 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5634 5635 Level: intermediate 5636 5637 Note: 5638 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 5639 using several randomly created vectors, see `MatMultEqual()`. 5640 5641 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5642 @*/ 5643 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5644 { 5645 PetscFunctionBegin; 5646 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5647 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5648 PetscValidType(A, 1); 5649 PetscValidType(B, 2); 5650 PetscAssertPointer(flg, 3); 5651 PetscCheckSameComm(A, 1, B, 2); 5652 MatCheckPreallocated(A, 1); 5653 MatCheckPreallocated(B, 2); 5654 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5655 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5656 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, 5657 B->cmap->N); 5658 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5659 PetscUseTypeMethod(A, equal, B, flg); 5660 } else { 5661 PetscCall(MatMultEqual(A, B, 10, flg)); 5662 } 5663 PetscFunctionReturn(PETSC_SUCCESS); 5664 } 5665 5666 /*@ 5667 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5668 matrices that are stored as vectors. Either of the two scaling 5669 matrices can be `NULL`. 5670 5671 Collective 5672 5673 Input Parameters: 5674 + mat - the matrix to be scaled 5675 . l - the left scaling vector (or `NULL`) 5676 - r - the right scaling vector (or `NULL`) 5677 5678 Level: intermediate 5679 5680 Note: 5681 `MatDiagonalScale()` computes $A = LAR$, where 5682 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5683 The L scales the rows of the matrix, the R scales the columns of the matrix. 5684 5685 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5686 @*/ 5687 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5688 { 5689 PetscFunctionBegin; 5690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5691 PetscValidType(mat, 1); 5692 if (l) { 5693 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5694 PetscCheckSameComm(mat, 1, l, 2); 5695 } 5696 if (r) { 5697 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5698 PetscCheckSameComm(mat, 1, r, 3); 5699 } 5700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5702 MatCheckPreallocated(mat, 1); 5703 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5704 5705 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5706 PetscUseTypeMethod(mat, diagonalscale, l, r); 5707 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5708 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5709 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5710 PetscFunctionReturn(PETSC_SUCCESS); 5711 } 5712 5713 /*@ 5714 MatScale - Scales all elements of a matrix by a given number. 5715 5716 Logically Collective 5717 5718 Input Parameters: 5719 + mat - the matrix to be scaled 5720 - a - the scaling value 5721 5722 Level: intermediate 5723 5724 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5725 @*/ 5726 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5727 { 5728 PetscFunctionBegin; 5729 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5730 PetscValidType(mat, 1); 5731 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5732 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5733 PetscValidLogicalCollectiveScalar(mat, a, 2); 5734 MatCheckPreallocated(mat, 1); 5735 5736 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5737 if (a != (PetscScalar)1.0) { 5738 PetscUseTypeMethod(mat, scale, a); 5739 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5740 } 5741 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5742 PetscFunctionReturn(PETSC_SUCCESS); 5743 } 5744 5745 /*@ 5746 MatNorm - Calculates various norms of a matrix. 5747 5748 Collective 5749 5750 Input Parameters: 5751 + mat - the matrix 5752 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5753 5754 Output Parameter: 5755 . nrm - the resulting norm 5756 5757 Level: intermediate 5758 5759 .seealso: [](ch_matrices), `Mat` 5760 @*/ 5761 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5762 { 5763 PetscFunctionBegin; 5764 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5765 PetscValidType(mat, 1); 5766 PetscAssertPointer(nrm, 3); 5767 5768 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5769 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5770 MatCheckPreallocated(mat, 1); 5771 5772 PetscUseTypeMethod(mat, norm, type, nrm); 5773 PetscFunctionReturn(PETSC_SUCCESS); 5774 } 5775 5776 /* 5777 This variable is used to prevent counting of MatAssemblyBegin() that 5778 are called from within a MatAssemblyEnd(). 5779 */ 5780 static PetscInt MatAssemblyEnd_InUse = 0; 5781 /*@ 5782 MatAssemblyBegin - Begins assembling the matrix. This routine should 5783 be called after completing all calls to `MatSetValues()`. 5784 5785 Collective 5786 5787 Input Parameters: 5788 + mat - the matrix 5789 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5790 5791 Level: beginner 5792 5793 Notes: 5794 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5795 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5796 5797 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5798 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5799 using the matrix. 5800 5801 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5802 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 5803 a global collective operation requiring all processes that share the matrix. 5804 5805 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5806 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5807 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5808 5809 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5810 @*/ 5811 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5812 { 5813 PetscFunctionBegin; 5814 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5815 PetscValidType(mat, 1); 5816 MatCheckPreallocated(mat, 1); 5817 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5818 if (mat->assembled) { 5819 mat->was_assembled = PETSC_TRUE; 5820 mat->assembled = PETSC_FALSE; 5821 } 5822 5823 if (!MatAssemblyEnd_InUse) { 5824 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5825 PetscTryTypeMethod(mat, assemblybegin, type); 5826 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5827 } else PetscTryTypeMethod(mat, assemblybegin, type); 5828 PetscFunctionReturn(PETSC_SUCCESS); 5829 } 5830 5831 /*@ 5832 MatAssembled - Indicates if a matrix has been assembled and is ready for 5833 use; for example, in matrix-vector product. 5834 5835 Not Collective 5836 5837 Input Parameter: 5838 . mat - the matrix 5839 5840 Output Parameter: 5841 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5842 5843 Level: advanced 5844 5845 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5846 @*/ 5847 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5848 { 5849 PetscFunctionBegin; 5850 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5851 PetscAssertPointer(assembled, 2); 5852 *assembled = mat->assembled; 5853 PetscFunctionReturn(PETSC_SUCCESS); 5854 } 5855 5856 /*@ 5857 MatAssemblyEnd - Completes assembling the matrix. This routine should 5858 be called after `MatAssemblyBegin()`. 5859 5860 Collective 5861 5862 Input Parameters: 5863 + mat - the matrix 5864 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5865 5866 Options Database Keys: 5867 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5868 . -mat_view ::ascii_info_detail - Prints more detailed info 5869 . -mat_view - Prints matrix in ASCII format 5870 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5871 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5872 . -display <name> - Sets display name (default is host) 5873 . -draw_pause <sec> - Sets number of seconds to pause after display 5874 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5875 . -viewer_socket_machine <machine> - Machine to use for socket 5876 . -viewer_socket_port <port> - Port number to use for socket 5877 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5878 5879 Level: beginner 5880 5881 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5882 @*/ 5883 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5884 { 5885 static PetscInt inassm = 0; 5886 PetscBool flg = PETSC_FALSE; 5887 5888 PetscFunctionBegin; 5889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5890 PetscValidType(mat, 1); 5891 5892 inassm++; 5893 MatAssemblyEnd_InUse++; 5894 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5895 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5896 PetscTryTypeMethod(mat, assemblyend, type); 5897 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5898 } else PetscTryTypeMethod(mat, assemblyend, type); 5899 5900 /* Flush assembly is not a true assembly */ 5901 if (type != MAT_FLUSH_ASSEMBLY) { 5902 if (mat->num_ass) { 5903 if (!mat->symmetry_eternal) { 5904 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5905 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5906 } 5907 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5908 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5909 } 5910 mat->num_ass++; 5911 mat->assembled = PETSC_TRUE; 5912 mat->ass_nonzerostate = mat->nonzerostate; 5913 } 5914 5915 mat->insertmode = NOT_SET_VALUES; 5916 MatAssemblyEnd_InUse--; 5917 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5918 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5919 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5920 5921 if (mat->checksymmetryonassembly) { 5922 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5923 if (flg) { 5924 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5925 } else { 5926 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5927 } 5928 } 5929 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5930 } 5931 inassm--; 5932 PetscFunctionReturn(PETSC_SUCCESS); 5933 } 5934 5935 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5936 /*@ 5937 MatSetOption - Sets a parameter option for a matrix. Some options 5938 may be specific to certain storage formats. Some options 5939 determine how values will be inserted (or added). Sorted, 5940 row-oriented input will generally assemble the fastest. The default 5941 is row-oriented. 5942 5943 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5944 5945 Input Parameters: 5946 + mat - the matrix 5947 . op - the option, one of those listed below (and possibly others), 5948 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5949 5950 Options Describing Matrix Structure: 5951 + `MAT_SPD` - symmetric positive definite 5952 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5953 . `MAT_HERMITIAN` - transpose is the complex conjugation 5954 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5955 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5956 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5957 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5958 5959 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5960 do not need to be computed (usually at a high cost) 5961 5962 Options For Use with `MatSetValues()`: 5963 Insert a logically dense subblock, which can be 5964 . `MAT_ROW_ORIENTED` - row-oriented (default) 5965 5966 These options reflect the data you pass in with `MatSetValues()`; it has 5967 nothing to do with how the data is stored internally in the matrix 5968 data structure. 5969 5970 When (re)assembling a matrix, we can restrict the input for 5971 efficiency/debugging purposes. These options include 5972 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5973 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5974 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5975 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5976 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5977 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5978 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5979 performance for very large process counts. 5980 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5981 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5982 functions, instead sending only neighbor messages. 5983 5984 Level: intermediate 5985 5986 Notes: 5987 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5988 5989 Some options are relevant only for particular matrix types and 5990 are thus ignored by others. Other options are not supported by 5991 certain matrix types and will generate an error message if set. 5992 5993 If using Fortran to compute a matrix, one may need to 5994 use the column-oriented option (or convert to the row-oriented 5995 format). 5996 5997 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5998 that would generate a new entry in the nonzero structure is instead 5999 ignored. Thus, if memory has not already been allocated for this particular 6000 data, then the insertion is ignored. For dense matrices, in which 6001 the entire array is allocated, no entries are ever ignored. 6002 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6003 6004 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6005 that would generate a new entry in the nonzero structure instead produces 6006 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 6007 6008 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6009 that would generate a new entry that has not been preallocated will 6010 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6011 only.) This is a useful flag when debugging matrix memory preallocation. 6012 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6013 6014 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6015 other processors should be dropped, rather than stashed. 6016 This is useful if you know that the "owning" processor is also 6017 always generating the correct matrix entries, so that PETSc need 6018 not transfer duplicate entries generated on another processor. 6019 6020 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6021 searches during matrix assembly. When this flag is set, the hash table 6022 is created during the first matrix assembly. This hash table is 6023 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6024 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6025 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6026 supported by `MATMPIBAIJ` format only. 6027 6028 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6029 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6030 6031 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6032 a zero location in the matrix 6033 6034 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6035 6036 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6037 zero row routines and thus improves performance for very large process counts. 6038 6039 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6040 part of the matrix (since they should match the upper triangular part). 6041 6042 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6043 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6044 with finite difference schemes with non-periodic boundary conditions. 6045 6046 Developer Note: 6047 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6048 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6049 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6050 not changed. 6051 6052 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6053 @*/ 6054 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6055 { 6056 PetscFunctionBegin; 6057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6058 if (op > 0) { 6059 PetscValidLogicalCollectiveEnum(mat, op, 2); 6060 PetscValidLogicalCollectiveBool(mat, flg, 3); 6061 } 6062 6063 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); 6064 6065 switch (op) { 6066 case MAT_FORCE_DIAGONAL_ENTRIES: 6067 mat->force_diagonals = flg; 6068 PetscFunctionReturn(PETSC_SUCCESS); 6069 case MAT_NO_OFF_PROC_ENTRIES: 6070 mat->nooffprocentries = flg; 6071 PetscFunctionReturn(PETSC_SUCCESS); 6072 case MAT_SUBSET_OFF_PROC_ENTRIES: 6073 mat->assembly_subset = flg; 6074 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6075 #if !defined(PETSC_HAVE_MPIUNI) 6076 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6077 #endif 6078 mat->stash.first_assembly_done = PETSC_FALSE; 6079 } 6080 PetscFunctionReturn(PETSC_SUCCESS); 6081 case MAT_NO_OFF_PROC_ZERO_ROWS: 6082 mat->nooffproczerorows = flg; 6083 PetscFunctionReturn(PETSC_SUCCESS); 6084 case MAT_SPD: 6085 if (flg) { 6086 mat->spd = PETSC_BOOL3_TRUE; 6087 mat->symmetric = PETSC_BOOL3_TRUE; 6088 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6089 } else { 6090 mat->spd = PETSC_BOOL3_FALSE; 6091 } 6092 break; 6093 case MAT_SYMMETRIC: 6094 mat->symmetric = PetscBoolToBool3(flg); 6095 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6096 #if !defined(PETSC_USE_COMPLEX) 6097 mat->hermitian = PetscBoolToBool3(flg); 6098 #endif 6099 break; 6100 case MAT_HERMITIAN: 6101 mat->hermitian = PetscBoolToBool3(flg); 6102 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6103 #if !defined(PETSC_USE_COMPLEX) 6104 mat->symmetric = PetscBoolToBool3(flg); 6105 #endif 6106 break; 6107 case MAT_STRUCTURALLY_SYMMETRIC: 6108 mat->structurally_symmetric = PetscBoolToBool3(flg); 6109 break; 6110 case MAT_SYMMETRY_ETERNAL: 6111 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"); 6112 mat->symmetry_eternal = flg; 6113 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6114 break; 6115 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6116 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"); 6117 mat->structural_symmetry_eternal = flg; 6118 break; 6119 case MAT_SPD_ETERNAL: 6120 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"); 6121 mat->spd_eternal = flg; 6122 if (flg) { 6123 mat->structural_symmetry_eternal = PETSC_TRUE; 6124 mat->symmetry_eternal = PETSC_TRUE; 6125 } 6126 break; 6127 case MAT_STRUCTURE_ONLY: 6128 mat->structure_only = flg; 6129 break; 6130 case MAT_SORTED_FULL: 6131 mat->sortedfull = flg; 6132 break; 6133 default: 6134 break; 6135 } 6136 PetscTryTypeMethod(mat, setoption, op, flg); 6137 PetscFunctionReturn(PETSC_SUCCESS); 6138 } 6139 6140 /*@ 6141 MatGetOption - Gets a parameter option that has been set for a matrix. 6142 6143 Logically Collective 6144 6145 Input Parameters: 6146 + mat - the matrix 6147 - op - the option, this only responds to certain options, check the code for which ones 6148 6149 Output Parameter: 6150 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6151 6152 Level: intermediate 6153 6154 Notes: 6155 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6156 6157 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6158 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6159 6160 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6161 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6162 @*/ 6163 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6164 { 6165 PetscFunctionBegin; 6166 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6167 PetscValidType(mat, 1); 6168 6169 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); 6170 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()"); 6171 6172 switch (op) { 6173 case MAT_NO_OFF_PROC_ENTRIES: 6174 *flg = mat->nooffprocentries; 6175 break; 6176 case MAT_NO_OFF_PROC_ZERO_ROWS: 6177 *flg = mat->nooffproczerorows; 6178 break; 6179 case MAT_SYMMETRIC: 6180 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6181 break; 6182 case MAT_HERMITIAN: 6183 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6184 break; 6185 case MAT_STRUCTURALLY_SYMMETRIC: 6186 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6187 break; 6188 case MAT_SPD: 6189 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6190 break; 6191 case MAT_SYMMETRY_ETERNAL: 6192 *flg = mat->symmetry_eternal; 6193 break; 6194 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6195 *flg = mat->symmetry_eternal; 6196 break; 6197 default: 6198 break; 6199 } 6200 PetscFunctionReturn(PETSC_SUCCESS); 6201 } 6202 6203 /*@ 6204 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6205 this routine retains the old nonzero structure. 6206 6207 Logically Collective 6208 6209 Input Parameter: 6210 . mat - the matrix 6211 6212 Level: intermediate 6213 6214 Note: 6215 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. 6216 See the Performance chapter of the users manual for information on preallocating matrices. 6217 6218 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6219 @*/ 6220 PetscErrorCode MatZeroEntries(Mat mat) 6221 { 6222 PetscFunctionBegin; 6223 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6224 PetscValidType(mat, 1); 6225 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6226 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"); 6227 MatCheckPreallocated(mat, 1); 6228 6229 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6230 PetscUseTypeMethod(mat, zeroentries); 6231 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6232 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6233 PetscFunctionReturn(PETSC_SUCCESS); 6234 } 6235 6236 /*@ 6237 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6238 of a set of rows and columns of a matrix. 6239 6240 Collective 6241 6242 Input Parameters: 6243 + mat - the matrix 6244 . numRows - the number of rows/columns to zero 6245 . rows - the global row indices 6246 . diag - value put in the diagonal of the eliminated rows 6247 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6248 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6249 6250 Level: intermediate 6251 6252 Notes: 6253 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6254 6255 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6256 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 6257 6258 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6259 Krylov method to take advantage of the known solution on the zeroed rows. 6260 6261 For the parallel case, all processes that share the matrix (i.e., 6262 those in the communicator used for matrix creation) MUST call this 6263 routine, regardless of whether any rows being zeroed are owned by 6264 them. 6265 6266 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6267 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 6268 missing. 6269 6270 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6271 list only rows local to itself). 6272 6273 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6274 6275 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6276 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6277 @*/ 6278 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6279 { 6280 PetscFunctionBegin; 6281 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6282 PetscValidType(mat, 1); 6283 if (numRows) PetscAssertPointer(rows, 3); 6284 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6285 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6286 MatCheckPreallocated(mat, 1); 6287 6288 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6289 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6290 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6291 PetscFunctionReturn(PETSC_SUCCESS); 6292 } 6293 6294 /*@ 6295 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6296 of a set of rows and columns of a matrix. 6297 6298 Collective 6299 6300 Input Parameters: 6301 + mat - the matrix 6302 . is - the rows to zero 6303 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6304 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6305 - b - optional vector of right-hand side, that will be adjusted by provided solution 6306 6307 Level: intermediate 6308 6309 Note: 6310 See `MatZeroRowsColumns()` for details on how this routine operates. 6311 6312 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6313 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6314 @*/ 6315 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6316 { 6317 PetscInt numRows; 6318 const PetscInt *rows; 6319 6320 PetscFunctionBegin; 6321 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6322 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6323 PetscValidType(mat, 1); 6324 PetscValidType(is, 2); 6325 PetscCall(ISGetLocalSize(is, &numRows)); 6326 PetscCall(ISGetIndices(is, &rows)); 6327 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6328 PetscCall(ISRestoreIndices(is, &rows)); 6329 PetscFunctionReturn(PETSC_SUCCESS); 6330 } 6331 6332 /*@ 6333 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6334 of a set of rows of a matrix. 6335 6336 Collective 6337 6338 Input Parameters: 6339 + mat - the matrix 6340 . numRows - the number of rows to zero 6341 . rows - the global row indices 6342 . diag - value put in the diagonal of the zeroed rows 6343 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6344 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6345 6346 Level: intermediate 6347 6348 Notes: 6349 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6350 6351 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6352 6353 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6354 Krylov method to take advantage of the known solution on the zeroed rows. 6355 6356 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) 6357 from the matrix. 6358 6359 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6360 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6361 formats this does not alter the nonzero structure. 6362 6363 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6364 of the matrix is not changed the values are 6365 merely zeroed. 6366 6367 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6368 formats can optionally remove the main diagonal entry from the 6369 nonzero structure as well, by passing 0.0 as the final argument). 6370 6371 For the parallel case, all processes that share the matrix (i.e., 6372 those in the communicator used for matrix creation) MUST call this 6373 routine, regardless of whether any rows being zeroed are owned by 6374 them. 6375 6376 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6377 list only rows local to itself). 6378 6379 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6380 owns that are to be zeroed. This saves a global synchronization in the implementation. 6381 6382 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6383 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6384 @*/ 6385 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6386 { 6387 PetscFunctionBegin; 6388 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6389 PetscValidType(mat, 1); 6390 if (numRows) PetscAssertPointer(rows, 3); 6391 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6392 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6393 MatCheckPreallocated(mat, 1); 6394 6395 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6396 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6397 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6398 PetscFunctionReturn(PETSC_SUCCESS); 6399 } 6400 6401 /*@ 6402 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6403 of a set of rows of a matrix indicated by an `IS` 6404 6405 Collective 6406 6407 Input Parameters: 6408 + mat - the matrix 6409 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6410 . diag - value put in all diagonals of eliminated rows 6411 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6412 - b - optional vector of right-hand side, that will be adjusted by provided solution 6413 6414 Level: intermediate 6415 6416 Note: 6417 See `MatZeroRows()` for details on how this routine operates. 6418 6419 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6420 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6421 @*/ 6422 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6423 { 6424 PetscInt numRows = 0; 6425 const PetscInt *rows = NULL; 6426 6427 PetscFunctionBegin; 6428 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6429 PetscValidType(mat, 1); 6430 if (is) { 6431 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6432 PetscCall(ISGetLocalSize(is, &numRows)); 6433 PetscCall(ISGetIndices(is, &rows)); 6434 } 6435 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6436 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6437 PetscFunctionReturn(PETSC_SUCCESS); 6438 } 6439 6440 /*@ 6441 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6442 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6443 6444 Collective 6445 6446 Input Parameters: 6447 + mat - the matrix 6448 . numRows - the number of rows to remove 6449 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6450 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6451 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6452 - b - optional vector of right-hand side, that will be adjusted by provided solution 6453 6454 Level: intermediate 6455 6456 Notes: 6457 See `MatZeroRows()` for details on how this routine operates. 6458 6459 The grid coordinates are across the entire grid, not just the local portion 6460 6461 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6462 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6463 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6464 `DM_BOUNDARY_PERIODIC` boundary type. 6465 6466 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 6467 a single value per point) you can skip filling those indices. 6468 6469 Fortran Note: 6470 `idxm` and `idxn` should be declared as 6471 .vb 6472 MatStencil idxm(4, m) 6473 .ve 6474 and the values inserted using 6475 .vb 6476 idxm(MatStencil_i, 1) = i 6477 idxm(MatStencil_j, 1) = j 6478 idxm(MatStencil_k, 1) = k 6479 idxm(MatStencil_c, 1) = c 6480 etc 6481 .ve 6482 6483 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6484 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6485 @*/ 6486 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6487 { 6488 PetscInt dim = mat->stencil.dim; 6489 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6490 PetscInt *dims = mat->stencil.dims + 1; 6491 PetscInt *starts = mat->stencil.starts; 6492 PetscInt *dxm = (PetscInt *)rows; 6493 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6494 6495 PetscFunctionBegin; 6496 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6497 PetscValidType(mat, 1); 6498 if (numRows) PetscAssertPointer(rows, 3); 6499 6500 PetscCall(PetscMalloc1(numRows, &jdxm)); 6501 for (i = 0; i < numRows; ++i) { 6502 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6503 for (j = 0; j < 3 - sdim; ++j) dxm++; 6504 /* Local index in X dir */ 6505 tmp = *dxm++ - starts[0]; 6506 /* Loop over remaining dimensions */ 6507 for (j = 0; j < dim - 1; ++j) { 6508 /* If nonlocal, set index to be negative */ 6509 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6510 /* Update local index */ 6511 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6512 } 6513 /* Skip component slot if necessary */ 6514 if (mat->stencil.noc) dxm++; 6515 /* Local row number */ 6516 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6517 } 6518 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6519 PetscCall(PetscFree(jdxm)); 6520 PetscFunctionReturn(PETSC_SUCCESS); 6521 } 6522 6523 /*@ 6524 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6525 of a set of rows and columns of a matrix. 6526 6527 Collective 6528 6529 Input Parameters: 6530 + mat - the matrix 6531 . numRows - the number of rows/columns to remove 6532 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6533 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6534 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6535 - b - optional vector of right-hand side, that will be adjusted by provided solution 6536 6537 Level: intermediate 6538 6539 Notes: 6540 See `MatZeroRowsColumns()` for details on how this routine operates. 6541 6542 The grid coordinates are across the entire grid, not just the local portion 6543 6544 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6545 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6546 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6547 `DM_BOUNDARY_PERIODIC` boundary type. 6548 6549 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 6550 a single value per point) you can skip filling those indices. 6551 6552 Fortran Note: 6553 `idxm` and `idxn` should be declared as 6554 .vb 6555 MatStencil idxm(4, m) 6556 .ve 6557 and the values inserted using 6558 .vb 6559 idxm(MatStencil_i, 1) = i 6560 idxm(MatStencil_j, 1) = j 6561 idxm(MatStencil_k, 1) = k 6562 idxm(MatStencil_c, 1) = c 6563 etc 6564 .ve 6565 6566 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6567 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6568 @*/ 6569 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6570 { 6571 PetscInt dim = mat->stencil.dim; 6572 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6573 PetscInt *dims = mat->stencil.dims + 1; 6574 PetscInt *starts = mat->stencil.starts; 6575 PetscInt *dxm = (PetscInt *)rows; 6576 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6577 6578 PetscFunctionBegin; 6579 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6580 PetscValidType(mat, 1); 6581 if (numRows) PetscAssertPointer(rows, 3); 6582 6583 PetscCall(PetscMalloc1(numRows, &jdxm)); 6584 for (i = 0; i < numRows; ++i) { 6585 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6586 for (j = 0; j < 3 - sdim; ++j) dxm++; 6587 /* Local index in X dir */ 6588 tmp = *dxm++ - starts[0]; 6589 /* Loop over remaining dimensions */ 6590 for (j = 0; j < dim - 1; ++j) { 6591 /* If nonlocal, set index to be negative */ 6592 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6593 /* Update local index */ 6594 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6595 } 6596 /* Skip component slot if necessary */ 6597 if (mat->stencil.noc) dxm++; 6598 /* Local row number */ 6599 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6600 } 6601 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6602 PetscCall(PetscFree(jdxm)); 6603 PetscFunctionReturn(PETSC_SUCCESS); 6604 } 6605 6606 /*@ 6607 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6608 of a set of rows of a matrix; using local numbering of rows. 6609 6610 Collective 6611 6612 Input Parameters: 6613 + mat - the matrix 6614 . numRows - the number of rows to remove 6615 . rows - the local row indices 6616 . diag - value put in all diagonals of eliminated rows 6617 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6618 - b - optional vector of right-hand side, that will be adjusted by provided solution 6619 6620 Level: intermediate 6621 6622 Notes: 6623 Before calling `MatZeroRowsLocal()`, the user must first set the 6624 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6625 6626 See `MatZeroRows()` for details on how this routine operates. 6627 6628 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6629 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6630 @*/ 6631 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6632 { 6633 PetscFunctionBegin; 6634 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6635 PetscValidType(mat, 1); 6636 if (numRows) PetscAssertPointer(rows, 3); 6637 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6638 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6639 MatCheckPreallocated(mat, 1); 6640 6641 if (mat->ops->zerorowslocal) { 6642 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6643 } else { 6644 IS is, newis; 6645 const PetscInt *newRows; 6646 6647 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6648 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6649 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6650 PetscCall(ISGetIndices(newis, &newRows)); 6651 PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b); 6652 PetscCall(ISRestoreIndices(newis, &newRows)); 6653 PetscCall(ISDestroy(&newis)); 6654 PetscCall(ISDestroy(&is)); 6655 } 6656 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6657 PetscFunctionReturn(PETSC_SUCCESS); 6658 } 6659 6660 /*@ 6661 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6662 of a set of rows of a matrix; using local numbering of rows. 6663 6664 Collective 6665 6666 Input Parameters: 6667 + mat - the matrix 6668 . is - index set of rows to remove 6669 . diag - value put in all diagonals of eliminated rows 6670 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6671 - b - optional vector of right-hand side, that will be adjusted by provided solution 6672 6673 Level: intermediate 6674 6675 Notes: 6676 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6677 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6678 6679 See `MatZeroRows()` for details on how this routine operates. 6680 6681 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6682 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6683 @*/ 6684 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6685 { 6686 PetscInt numRows; 6687 const PetscInt *rows; 6688 6689 PetscFunctionBegin; 6690 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6691 PetscValidType(mat, 1); 6692 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6693 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6694 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6695 MatCheckPreallocated(mat, 1); 6696 6697 PetscCall(ISGetLocalSize(is, &numRows)); 6698 PetscCall(ISGetIndices(is, &rows)); 6699 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6700 PetscCall(ISRestoreIndices(is, &rows)); 6701 PetscFunctionReturn(PETSC_SUCCESS); 6702 } 6703 6704 /*@ 6705 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6706 of a set of rows and columns of a matrix; using local numbering of rows. 6707 6708 Collective 6709 6710 Input Parameters: 6711 + mat - the matrix 6712 . numRows - the number of rows to remove 6713 . rows - the global row indices 6714 . diag - value put in all diagonals of eliminated rows 6715 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6716 - b - optional vector of right-hand side, that will be adjusted by provided solution 6717 6718 Level: intermediate 6719 6720 Notes: 6721 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6722 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6723 6724 See `MatZeroRowsColumns()` for details on how this routine operates. 6725 6726 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6727 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6728 @*/ 6729 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6730 { 6731 IS is, newis; 6732 const PetscInt *newRows; 6733 6734 PetscFunctionBegin; 6735 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6736 PetscValidType(mat, 1); 6737 if (numRows) PetscAssertPointer(rows, 3); 6738 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6739 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6740 MatCheckPreallocated(mat, 1); 6741 6742 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6743 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is)); 6744 PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis)); 6745 PetscCall(ISGetIndices(newis, &newRows)); 6746 PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b); 6747 PetscCall(ISRestoreIndices(newis, &newRows)); 6748 PetscCall(ISDestroy(&newis)); 6749 PetscCall(ISDestroy(&is)); 6750 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6751 PetscFunctionReturn(PETSC_SUCCESS); 6752 } 6753 6754 /*@ 6755 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6756 of a set of rows and columns of a matrix; using local numbering of rows. 6757 6758 Collective 6759 6760 Input Parameters: 6761 + mat - the matrix 6762 . is - index set of rows to remove 6763 . diag - value put in all diagonals of eliminated rows 6764 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6765 - b - optional vector of right-hand side, that will be adjusted by provided solution 6766 6767 Level: intermediate 6768 6769 Notes: 6770 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6771 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6772 6773 See `MatZeroRowsColumns()` for details on how this routine operates. 6774 6775 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6776 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6777 @*/ 6778 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6779 { 6780 PetscInt numRows; 6781 const PetscInt *rows; 6782 6783 PetscFunctionBegin; 6784 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6785 PetscValidType(mat, 1); 6786 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6787 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6788 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6789 MatCheckPreallocated(mat, 1); 6790 6791 PetscCall(ISGetLocalSize(is, &numRows)); 6792 PetscCall(ISGetIndices(is, &rows)); 6793 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6794 PetscCall(ISRestoreIndices(is, &rows)); 6795 PetscFunctionReturn(PETSC_SUCCESS); 6796 } 6797 6798 /*@ 6799 MatGetSize - Returns the numbers of rows and columns in a matrix. 6800 6801 Not Collective 6802 6803 Input Parameter: 6804 . mat - the matrix 6805 6806 Output Parameters: 6807 + m - the number of global rows 6808 - n - the number of global columns 6809 6810 Level: beginner 6811 6812 Note: 6813 Both output parameters can be `NULL` on input. 6814 6815 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6816 @*/ 6817 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6818 { 6819 PetscFunctionBegin; 6820 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6821 if (m) *m = mat->rmap->N; 6822 if (n) *n = mat->cmap->N; 6823 PetscFunctionReturn(PETSC_SUCCESS); 6824 } 6825 6826 /*@ 6827 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6828 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6829 6830 Not Collective 6831 6832 Input Parameter: 6833 . mat - the matrix 6834 6835 Output Parameters: 6836 + m - the number of local rows, use `NULL` to not obtain this value 6837 - n - the number of local columns, use `NULL` to not obtain this value 6838 6839 Level: beginner 6840 6841 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6842 @*/ 6843 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6844 { 6845 PetscFunctionBegin; 6846 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6847 if (m) PetscAssertPointer(m, 2); 6848 if (n) PetscAssertPointer(n, 3); 6849 if (m) *m = mat->rmap->n; 6850 if (n) *n = mat->cmap->n; 6851 PetscFunctionReturn(PETSC_SUCCESS); 6852 } 6853 6854 /*@ 6855 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6856 vector one multiplies this matrix by that are owned by this processor. 6857 6858 Not Collective, unless matrix has not been allocated, then collective 6859 6860 Input Parameter: 6861 . mat - the matrix 6862 6863 Output Parameters: 6864 + m - the global index of the first local column, use `NULL` to not obtain this value 6865 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6866 6867 Level: developer 6868 6869 Notes: 6870 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6871 6872 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6873 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6874 6875 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6876 the local values in the matrix. 6877 6878 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6879 Layouts](sec_matlayout) for details on matrix layouts. 6880 6881 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6882 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6883 @*/ 6884 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6885 { 6886 PetscFunctionBegin; 6887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6888 PetscValidType(mat, 1); 6889 if (m) PetscAssertPointer(m, 2); 6890 if (n) PetscAssertPointer(n, 3); 6891 MatCheckPreallocated(mat, 1); 6892 if (m) *m = mat->cmap->rstart; 6893 if (n) *n = mat->cmap->rend; 6894 PetscFunctionReturn(PETSC_SUCCESS); 6895 } 6896 6897 /*@ 6898 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6899 this MPI process. 6900 6901 Not Collective 6902 6903 Input Parameter: 6904 . mat - the matrix 6905 6906 Output Parameters: 6907 + m - the global index of the first local row, use `NULL` to not obtain this value 6908 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6909 6910 Level: beginner 6911 6912 Notes: 6913 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6914 6915 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6916 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6917 6918 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6919 the local values in the matrix. 6920 6921 The high argument is one more than the last element stored locally. 6922 6923 For all matrices it returns the range of matrix rows associated with rows of a vector that 6924 would contain the result of a matrix vector product with this matrix. See [Matrix 6925 Layouts](sec_matlayout) for details on matrix layouts. 6926 6927 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6928 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6929 @*/ 6930 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6931 { 6932 PetscFunctionBegin; 6933 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6934 PetscValidType(mat, 1); 6935 if (m) PetscAssertPointer(m, 2); 6936 if (n) PetscAssertPointer(n, 3); 6937 MatCheckPreallocated(mat, 1); 6938 if (m) *m = mat->rmap->rstart; 6939 if (n) *n = mat->rmap->rend; 6940 PetscFunctionReturn(PETSC_SUCCESS); 6941 } 6942 6943 /*@C 6944 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6945 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6946 6947 Not Collective, unless matrix has not been allocated 6948 6949 Input Parameter: 6950 . mat - the matrix 6951 6952 Output Parameter: 6953 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6954 where `size` is the number of MPI processes used by `mat` 6955 6956 Level: beginner 6957 6958 Notes: 6959 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6960 6961 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6962 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6963 6964 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6965 the local values in the matrix. 6966 6967 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6968 would contain the result of a matrix vector product with this matrix. See [Matrix 6969 Layouts](sec_matlayout) for details on matrix layouts. 6970 6971 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6972 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6973 `DMDAGetGhostCorners()`, `DM` 6974 @*/ 6975 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6976 { 6977 PetscFunctionBegin; 6978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6979 PetscValidType(mat, 1); 6980 MatCheckPreallocated(mat, 1); 6981 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6982 PetscFunctionReturn(PETSC_SUCCESS); 6983 } 6984 6985 /*@C 6986 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6987 vector one multiplies this vector by that are owned by each processor. 6988 6989 Not Collective, unless matrix has not been allocated 6990 6991 Input Parameter: 6992 . mat - the matrix 6993 6994 Output Parameter: 6995 . ranges - start of each processors portion plus one more than the total length at the end 6996 6997 Level: beginner 6998 6999 Notes: 7000 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7001 7002 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7003 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7004 7005 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7006 the local values in the matrix. 7007 7008 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7009 Layouts](sec_matlayout) for details on matrix layouts. 7010 7011 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7012 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7013 `DMDAGetGhostCorners()`, `DM` 7014 @*/ 7015 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7016 { 7017 PetscFunctionBegin; 7018 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7019 PetscValidType(mat, 1); 7020 MatCheckPreallocated(mat, 1); 7021 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7022 PetscFunctionReturn(PETSC_SUCCESS); 7023 } 7024 7025 /*@ 7026 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7027 7028 Not Collective 7029 7030 Input Parameter: 7031 . A - matrix 7032 7033 Output Parameters: 7034 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7035 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7036 7037 Level: intermediate 7038 7039 Note: 7040 You should call `ISDestroy()` on the returned `IS` 7041 7042 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7043 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7044 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7045 details on matrix layouts. 7046 7047 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7048 @*/ 7049 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7050 { 7051 PetscErrorCode (*f)(Mat, IS *, IS *); 7052 7053 PetscFunctionBegin; 7054 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7055 PetscValidType(A, 1); 7056 MatCheckPreallocated(A, 1); 7057 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7058 if (f) { 7059 PetscCall((*f)(A, rows, cols)); 7060 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7061 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7062 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7063 } 7064 PetscFunctionReturn(PETSC_SUCCESS); 7065 } 7066 7067 /*@ 7068 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7069 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7070 to complete the factorization. 7071 7072 Collective 7073 7074 Input Parameters: 7075 + fact - the factorized matrix obtained with `MatGetFactor()` 7076 . mat - the matrix 7077 . row - row permutation 7078 . col - column permutation 7079 - info - structure containing 7080 .vb 7081 levels - number of levels of fill. 7082 expected fill - as ratio of original fill. 7083 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7084 missing diagonal entries) 7085 .ve 7086 7087 Level: developer 7088 7089 Notes: 7090 See [Matrix Factorization](sec_matfactor) for additional information. 7091 7092 Most users should employ the `KSP` interface for linear solvers 7093 instead of working directly with matrix algebra routines such as this. 7094 See, e.g., `KSPCreate()`. 7095 7096 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7097 7098 Developer Note: 7099 The Fortran interface is not autogenerated as the 7100 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7101 7102 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7103 `MatGetOrdering()`, `MatFactorInfo` 7104 @*/ 7105 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7106 { 7107 PetscFunctionBegin; 7108 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7109 PetscValidType(mat, 2); 7110 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7111 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7112 PetscAssertPointer(info, 5); 7113 PetscAssertPointer(fact, 1); 7114 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7115 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7116 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7117 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7118 MatCheckPreallocated(mat, 2); 7119 7120 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7121 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7122 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7123 PetscFunctionReturn(PETSC_SUCCESS); 7124 } 7125 7126 /*@ 7127 MatICCFactorSymbolic - Performs symbolic incomplete 7128 Cholesky factorization for a symmetric matrix. Use 7129 `MatCholeskyFactorNumeric()` to complete the factorization. 7130 7131 Collective 7132 7133 Input Parameters: 7134 + fact - the factorized matrix obtained with `MatGetFactor()` 7135 . mat - the matrix to be factored 7136 . perm - row and column permutation 7137 - info - structure containing 7138 .vb 7139 levels - number of levels of fill. 7140 expected fill - as ratio of original fill. 7141 .ve 7142 7143 Level: developer 7144 7145 Notes: 7146 Most users should employ the `KSP` interface for linear solvers 7147 instead of working directly with matrix algebra routines such as this. 7148 See, e.g., `KSPCreate()`. 7149 7150 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7151 7152 Developer Note: 7153 The Fortran interface is not autogenerated as the 7154 interface definition cannot be generated correctly [due to `MatFactorInfo`] 7155 7156 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7157 @*/ 7158 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7159 { 7160 PetscFunctionBegin; 7161 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7162 PetscValidType(mat, 2); 7163 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7164 PetscAssertPointer(info, 4); 7165 PetscAssertPointer(fact, 1); 7166 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7167 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7168 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7169 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7170 MatCheckPreallocated(mat, 2); 7171 7172 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7173 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7174 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7175 PetscFunctionReturn(PETSC_SUCCESS); 7176 } 7177 7178 /*@C 7179 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7180 points to an array of valid matrices, they may be reused to store the new 7181 submatrices. 7182 7183 Collective 7184 7185 Input Parameters: 7186 + mat - the matrix 7187 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7188 . irow - index set of rows to extract 7189 . icol - index set of columns to extract 7190 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7191 7192 Output Parameter: 7193 . submat - the array of submatrices 7194 7195 Level: advanced 7196 7197 Notes: 7198 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7199 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7200 to extract a parallel submatrix. 7201 7202 Some matrix types place restrictions on the row and column 7203 indices, such as that they be sorted or that they be equal to each other. 7204 7205 The index sets may not have duplicate entries. 7206 7207 When extracting submatrices from a parallel matrix, each processor can 7208 form a different submatrix by setting the rows and columns of its 7209 individual index sets according to the local submatrix desired. 7210 7211 When finished using the submatrices, the user should destroy 7212 them with `MatDestroySubMatrices()`. 7213 7214 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7215 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7216 7217 This routine creates the matrices in submat; you should NOT create them before 7218 calling it. It also allocates the array of matrix pointers submat. 7219 7220 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7221 request one row/column in a block, they must request all rows/columns that are in 7222 that block. For example, if the block size is 2 you cannot request just row 0 and 7223 column 0. 7224 7225 Fortran Note: 7226 .vb 7227 Mat, pointer :: submat(:) 7228 .ve 7229 7230 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7231 @*/ 7232 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7233 { 7234 PetscInt i; 7235 PetscBool eq; 7236 7237 PetscFunctionBegin; 7238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7239 PetscValidType(mat, 1); 7240 if (n) { 7241 PetscAssertPointer(irow, 3); 7242 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7243 PetscAssertPointer(icol, 4); 7244 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7245 } 7246 PetscAssertPointer(submat, 6); 7247 if (n && scall == MAT_REUSE_MATRIX) { 7248 PetscAssertPointer(*submat, 6); 7249 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7250 } 7251 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7252 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7253 MatCheckPreallocated(mat, 1); 7254 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7255 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7256 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7257 for (i = 0; i < n; i++) { 7258 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7259 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7260 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7261 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7262 if (mat->boundtocpu && mat->bindingpropagates) { 7263 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7264 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7265 } 7266 #endif 7267 } 7268 PetscFunctionReturn(PETSC_SUCCESS); 7269 } 7270 7271 /*@C 7272 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7273 7274 Collective 7275 7276 Input Parameters: 7277 + mat - the matrix 7278 . n - the number of submatrixes to be extracted 7279 . irow - index set of rows to extract 7280 . icol - index set of columns to extract 7281 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7282 7283 Output Parameter: 7284 . submat - the array of submatrices 7285 7286 Level: advanced 7287 7288 Note: 7289 This is used by `PCGASM` 7290 7291 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7292 @*/ 7293 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7294 { 7295 PetscInt i; 7296 PetscBool eq; 7297 7298 PetscFunctionBegin; 7299 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7300 PetscValidType(mat, 1); 7301 if (n) { 7302 PetscAssertPointer(irow, 3); 7303 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7304 PetscAssertPointer(icol, 4); 7305 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7306 } 7307 PetscAssertPointer(submat, 6); 7308 if (n && scall == MAT_REUSE_MATRIX) { 7309 PetscAssertPointer(*submat, 6); 7310 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7311 } 7312 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7313 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7314 MatCheckPreallocated(mat, 1); 7315 7316 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7317 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7318 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7319 for (i = 0; i < n; i++) { 7320 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7321 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7322 } 7323 PetscFunctionReturn(PETSC_SUCCESS); 7324 } 7325 7326 /*@C 7327 MatDestroyMatrices - Destroys an array of matrices 7328 7329 Collective 7330 7331 Input Parameters: 7332 + n - the number of local matrices 7333 - mat - the matrices (this is a pointer to the array of matrices) 7334 7335 Level: advanced 7336 7337 Notes: 7338 Frees not only the matrices, but also the array that contains the matrices 7339 7340 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7341 7342 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7343 @*/ 7344 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7345 { 7346 PetscInt i; 7347 7348 PetscFunctionBegin; 7349 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7350 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7351 PetscAssertPointer(mat, 2); 7352 7353 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7354 7355 /* memory is allocated even if n = 0 */ 7356 PetscCall(PetscFree(*mat)); 7357 PetscFunctionReturn(PETSC_SUCCESS); 7358 } 7359 7360 /*@C 7361 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7362 7363 Collective 7364 7365 Input Parameters: 7366 + n - the number of local matrices 7367 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7368 7369 Level: advanced 7370 7371 Note: 7372 Frees not only the matrices, but also the array that contains the matrices 7373 7374 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7375 @*/ 7376 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7377 { 7378 Mat mat0; 7379 7380 PetscFunctionBegin; 7381 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7382 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7383 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7384 PetscAssertPointer(mat, 2); 7385 7386 mat0 = (*mat)[0]; 7387 if (mat0 && mat0->ops->destroysubmatrices) { 7388 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7389 } else { 7390 PetscCall(MatDestroyMatrices(n, mat)); 7391 } 7392 PetscFunctionReturn(PETSC_SUCCESS); 7393 } 7394 7395 /*@ 7396 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7397 7398 Collective 7399 7400 Input Parameter: 7401 . mat - the matrix 7402 7403 Output Parameter: 7404 . matstruct - the sequential matrix with the nonzero structure of `mat` 7405 7406 Level: developer 7407 7408 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7409 @*/ 7410 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7411 { 7412 PetscFunctionBegin; 7413 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7414 PetscAssertPointer(matstruct, 2); 7415 7416 PetscValidType(mat, 1); 7417 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7418 MatCheckPreallocated(mat, 1); 7419 7420 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7421 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7422 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7423 PetscFunctionReturn(PETSC_SUCCESS); 7424 } 7425 7426 /*@C 7427 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7428 7429 Collective 7430 7431 Input Parameter: 7432 . mat - the matrix 7433 7434 Level: advanced 7435 7436 Note: 7437 This is not needed, one can just call `MatDestroy()` 7438 7439 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7440 @*/ 7441 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7442 { 7443 PetscFunctionBegin; 7444 PetscAssertPointer(mat, 1); 7445 PetscCall(MatDestroy(mat)); 7446 PetscFunctionReturn(PETSC_SUCCESS); 7447 } 7448 7449 /*@ 7450 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7451 replaces the index sets by larger ones that represent submatrices with 7452 additional overlap. 7453 7454 Collective 7455 7456 Input Parameters: 7457 + mat - the matrix 7458 . n - the number of index sets 7459 . is - the array of index sets (these index sets will changed during the call) 7460 - ov - the additional overlap requested 7461 7462 Options Database Key: 7463 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7464 7465 Level: developer 7466 7467 Note: 7468 The computed overlap preserves the matrix block sizes when the blocks are square. 7469 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7470 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7471 7472 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7473 @*/ 7474 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7475 { 7476 PetscInt i, bs, cbs; 7477 7478 PetscFunctionBegin; 7479 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7480 PetscValidType(mat, 1); 7481 PetscValidLogicalCollectiveInt(mat, n, 2); 7482 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7483 if (n) { 7484 PetscAssertPointer(is, 3); 7485 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7486 } 7487 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7488 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7489 MatCheckPreallocated(mat, 1); 7490 7491 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7492 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7493 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7494 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7495 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7496 if (bs == cbs) { 7497 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7498 } 7499 PetscFunctionReturn(PETSC_SUCCESS); 7500 } 7501 7502 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7503 7504 /*@ 7505 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7506 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7507 additional overlap. 7508 7509 Collective 7510 7511 Input Parameters: 7512 + mat - the matrix 7513 . n - the number of index sets 7514 . is - the array of index sets (these index sets will changed during the call) 7515 - ov - the additional overlap requested 7516 7517 ` Options Database Key: 7518 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7519 7520 Level: developer 7521 7522 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7523 @*/ 7524 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7525 { 7526 PetscInt i; 7527 7528 PetscFunctionBegin; 7529 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7530 PetscValidType(mat, 1); 7531 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7532 if (n) { 7533 PetscAssertPointer(is, 3); 7534 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7535 } 7536 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7537 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7538 MatCheckPreallocated(mat, 1); 7539 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7540 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7541 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7542 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7543 PetscFunctionReturn(PETSC_SUCCESS); 7544 } 7545 7546 /*@ 7547 MatGetBlockSize - Returns the matrix block size. 7548 7549 Not Collective 7550 7551 Input Parameter: 7552 . mat - the matrix 7553 7554 Output Parameter: 7555 . bs - block size 7556 7557 Level: intermediate 7558 7559 Notes: 7560 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7561 7562 If the block size has not been set yet this routine returns 1. 7563 7564 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7565 @*/ 7566 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7567 { 7568 PetscFunctionBegin; 7569 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7570 PetscAssertPointer(bs, 2); 7571 *bs = mat->rmap->bs; 7572 PetscFunctionReturn(PETSC_SUCCESS); 7573 } 7574 7575 /*@ 7576 MatGetBlockSizes - Returns the matrix block row and column sizes. 7577 7578 Not Collective 7579 7580 Input Parameter: 7581 . mat - the matrix 7582 7583 Output Parameters: 7584 + rbs - row block size 7585 - cbs - column block size 7586 7587 Level: intermediate 7588 7589 Notes: 7590 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7591 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7592 7593 If a block size has not been set yet this routine returns 1. 7594 7595 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7596 @*/ 7597 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7598 { 7599 PetscFunctionBegin; 7600 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7601 if (rbs) PetscAssertPointer(rbs, 2); 7602 if (cbs) PetscAssertPointer(cbs, 3); 7603 if (rbs) *rbs = mat->rmap->bs; 7604 if (cbs) *cbs = mat->cmap->bs; 7605 PetscFunctionReturn(PETSC_SUCCESS); 7606 } 7607 7608 /*@ 7609 MatSetBlockSize - Sets the matrix block size. 7610 7611 Logically Collective 7612 7613 Input Parameters: 7614 + mat - the matrix 7615 - bs - block size 7616 7617 Level: intermediate 7618 7619 Notes: 7620 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7621 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7622 7623 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7624 is compatible with the matrix local sizes. 7625 7626 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7627 @*/ 7628 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7629 { 7630 PetscFunctionBegin; 7631 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7632 PetscValidLogicalCollectiveInt(mat, bs, 2); 7633 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7634 PetscFunctionReturn(PETSC_SUCCESS); 7635 } 7636 7637 typedef struct { 7638 PetscInt n; 7639 IS *is; 7640 Mat *mat; 7641 PetscObjectState nonzerostate; 7642 Mat C; 7643 } EnvelopeData; 7644 7645 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7646 { 7647 EnvelopeData *edata = (EnvelopeData *)*ptr; 7648 7649 PetscFunctionBegin; 7650 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7651 PetscCall(PetscFree(edata->is)); 7652 PetscCall(PetscFree(edata)); 7653 PetscFunctionReturn(PETSC_SUCCESS); 7654 } 7655 7656 /*@ 7657 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7658 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7659 7660 Collective 7661 7662 Input Parameter: 7663 . mat - the matrix 7664 7665 Level: intermediate 7666 7667 Notes: 7668 There can be zeros within the blocks 7669 7670 The blocks can overlap between processes, including laying on more than two processes 7671 7672 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7673 @*/ 7674 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7675 { 7676 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7677 PetscInt *diag, *odiag, sc; 7678 VecScatter scatter; 7679 PetscScalar *seqv; 7680 const PetscScalar *parv; 7681 const PetscInt *ia, *ja; 7682 PetscBool set, flag, done; 7683 Mat AA = mat, A; 7684 MPI_Comm comm; 7685 PetscMPIInt rank, size, tag; 7686 MPI_Status status; 7687 PetscContainer container; 7688 EnvelopeData *edata; 7689 Vec seq, par; 7690 IS isglobal; 7691 7692 PetscFunctionBegin; 7693 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7694 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7695 if (!set || !flag) { 7696 /* TODO: only needs nonzero structure of transpose */ 7697 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7698 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7699 } 7700 PetscCall(MatAIJGetLocalMat(AA, &A)); 7701 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7702 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7703 7704 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7705 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7706 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7707 PetscCallMPI(MPI_Comm_size(comm, &size)); 7708 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7709 7710 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7711 7712 if (rank > 0) { 7713 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7714 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7715 } 7716 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7717 for (i = 0; i < n; i++) { 7718 env = PetscMax(env, ja[ia[i + 1] - 1]); 7719 II = rstart + i; 7720 if (env == II) { 7721 starts[lblocks] = tbs; 7722 sizes[lblocks++] = 1 + II - tbs; 7723 tbs = 1 + II; 7724 } 7725 } 7726 if (rank < size - 1) { 7727 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7728 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7729 } 7730 7731 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7732 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7733 PetscCall(MatDestroy(&A)); 7734 7735 PetscCall(PetscNew(&edata)); 7736 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7737 edata->n = lblocks; 7738 /* create IS needed for extracting blocks from the original matrix */ 7739 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7740 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7741 7742 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7743 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7744 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7745 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7746 PetscCall(MatSetType(edata->C, MATAIJ)); 7747 7748 /* Communicate the start and end of each row, from each block to the correct rank */ 7749 /* TODO: Use PetscSF instead of VecScatter */ 7750 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7751 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7752 PetscCall(VecGetArrayWrite(seq, &seqv)); 7753 for (PetscInt i = 0; i < lblocks; i++) { 7754 for (PetscInt j = 0; j < sizes[i]; j++) { 7755 seqv[cnt] = starts[i]; 7756 seqv[cnt + 1] = starts[i] + sizes[i]; 7757 cnt += 2; 7758 } 7759 } 7760 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7761 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7762 sc -= cnt; 7763 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7764 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7765 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7766 PetscCall(ISDestroy(&isglobal)); 7767 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7768 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7769 PetscCall(VecScatterDestroy(&scatter)); 7770 PetscCall(VecDestroy(&seq)); 7771 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7772 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7773 PetscCall(VecGetArrayRead(par, &parv)); 7774 cnt = 0; 7775 PetscCall(MatGetSize(mat, NULL, &n)); 7776 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7777 PetscInt start, end, d = 0, od = 0; 7778 7779 start = (PetscInt)PetscRealPart(parv[cnt]); 7780 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7781 cnt += 2; 7782 7783 if (start < cstart) { 7784 od += cstart - start + n - cend; 7785 d += cend - cstart; 7786 } else if (start < cend) { 7787 od += n - cend; 7788 d += cend - start; 7789 } else od += n - start; 7790 if (end <= cstart) { 7791 od -= cstart - end + n - cend; 7792 d -= cend - cstart; 7793 } else if (end < cend) { 7794 od -= n - cend; 7795 d -= cend - end; 7796 } else od -= n - end; 7797 7798 odiag[i] = od; 7799 diag[i] = d; 7800 } 7801 PetscCall(VecRestoreArrayRead(par, &parv)); 7802 PetscCall(VecDestroy(&par)); 7803 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7804 PetscCall(PetscFree2(diag, odiag)); 7805 PetscCall(PetscFree2(sizes, starts)); 7806 7807 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7808 PetscCall(PetscContainerSetPointer(container, edata)); 7809 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7810 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7811 PetscCall(PetscObjectDereference((PetscObject)container)); 7812 PetscFunctionReturn(PETSC_SUCCESS); 7813 } 7814 7815 /*@ 7816 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7817 7818 Collective 7819 7820 Input Parameters: 7821 + A - the matrix 7822 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7823 7824 Output Parameter: 7825 . C - matrix with inverted block diagonal of `A` 7826 7827 Level: advanced 7828 7829 Note: 7830 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7831 7832 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7833 @*/ 7834 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7835 { 7836 PetscContainer container; 7837 EnvelopeData *edata; 7838 PetscObjectState nonzerostate; 7839 7840 PetscFunctionBegin; 7841 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7842 if (!container) { 7843 PetscCall(MatComputeVariableBlockEnvelope(A)); 7844 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7845 } 7846 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7847 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7848 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7849 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7850 7851 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7852 *C = edata->C; 7853 7854 for (PetscInt i = 0; i < edata->n; i++) { 7855 Mat D; 7856 PetscScalar *dvalues; 7857 7858 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7859 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7860 PetscCall(MatSeqDenseInvert(D)); 7861 PetscCall(MatDenseGetArray(D, &dvalues)); 7862 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7863 PetscCall(MatDestroy(&D)); 7864 } 7865 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7866 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7867 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7868 PetscFunctionReturn(PETSC_SUCCESS); 7869 } 7870 7871 /*@ 7872 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7873 7874 Not Collective 7875 7876 Input Parameters: 7877 + mat - the matrix 7878 . nblocks - the number of blocks on this process, each block can only exist on a single process 7879 - bsizes - the block sizes 7880 7881 Level: intermediate 7882 7883 Notes: 7884 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7885 7886 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. 7887 7888 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7889 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7890 @*/ 7891 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7892 { 7893 PetscInt ncnt = 0, nlocal; 7894 7895 PetscFunctionBegin; 7896 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7897 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7898 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); 7899 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7900 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); 7901 PetscCall(PetscFree(mat->bsizes)); 7902 mat->nblocks = nblocks; 7903 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7904 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7905 PetscFunctionReturn(PETSC_SUCCESS); 7906 } 7907 7908 /*@C 7909 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7910 7911 Not Collective; No Fortran Support 7912 7913 Input Parameter: 7914 . mat - the matrix 7915 7916 Output Parameters: 7917 + nblocks - the number of blocks on this process 7918 - bsizes - the block sizes 7919 7920 Level: intermediate 7921 7922 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7923 @*/ 7924 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7925 { 7926 PetscFunctionBegin; 7927 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7928 if (nblocks) *nblocks = mat->nblocks; 7929 if (bsizes) *bsizes = mat->bsizes; 7930 PetscFunctionReturn(PETSC_SUCCESS); 7931 } 7932 7933 /*@ 7934 MatSetBlockSizes - Sets the matrix block row and column sizes. 7935 7936 Logically Collective 7937 7938 Input Parameters: 7939 + mat - the matrix 7940 . rbs - row block size 7941 - cbs - column block size 7942 7943 Level: intermediate 7944 7945 Notes: 7946 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 7947 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7948 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7949 7950 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 7951 are compatible with the matrix local sizes. 7952 7953 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 7954 7955 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 7956 @*/ 7957 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 7958 { 7959 PetscFunctionBegin; 7960 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7961 PetscValidLogicalCollectiveInt(mat, rbs, 2); 7962 PetscValidLogicalCollectiveInt(mat, cbs, 3); 7963 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 7964 if (mat->rmap->refcnt) { 7965 ISLocalToGlobalMapping l2g = NULL; 7966 PetscLayout nmap = NULL; 7967 7968 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 7969 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 7970 PetscCall(PetscLayoutDestroy(&mat->rmap)); 7971 mat->rmap = nmap; 7972 mat->rmap->mapping = l2g; 7973 } 7974 if (mat->cmap->refcnt) { 7975 ISLocalToGlobalMapping l2g = NULL; 7976 PetscLayout nmap = NULL; 7977 7978 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 7979 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 7980 PetscCall(PetscLayoutDestroy(&mat->cmap)); 7981 mat->cmap = nmap; 7982 mat->cmap->mapping = l2g; 7983 } 7984 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 7985 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 7986 PetscFunctionReturn(PETSC_SUCCESS); 7987 } 7988 7989 /*@ 7990 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 7991 7992 Logically Collective 7993 7994 Input Parameters: 7995 + mat - the matrix 7996 . fromRow - matrix from which to copy row block size 7997 - fromCol - matrix from which to copy column block size (can be same as fromRow) 7998 7999 Level: developer 8000 8001 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8002 @*/ 8003 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8004 { 8005 PetscFunctionBegin; 8006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8007 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8008 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8009 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8010 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8011 PetscFunctionReturn(PETSC_SUCCESS); 8012 } 8013 8014 /*@ 8015 MatResidual - Default routine to calculate the residual r = b - Ax 8016 8017 Collective 8018 8019 Input Parameters: 8020 + mat - the matrix 8021 . b - the right-hand-side 8022 - x - the approximate solution 8023 8024 Output Parameter: 8025 . r - location to store the residual 8026 8027 Level: developer 8028 8029 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8030 @*/ 8031 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8032 { 8033 PetscFunctionBegin; 8034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8035 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8036 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8037 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8038 PetscValidType(mat, 1); 8039 MatCheckPreallocated(mat, 1); 8040 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8041 if (!mat->ops->residual) { 8042 PetscCall(MatMult(mat, x, r)); 8043 PetscCall(VecAYPX(r, -1.0, b)); 8044 } else { 8045 PetscUseTypeMethod(mat, residual, b, x, r); 8046 } 8047 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8048 PetscFunctionReturn(PETSC_SUCCESS); 8049 } 8050 8051 /*@C 8052 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8053 8054 Collective 8055 8056 Input Parameters: 8057 + mat - the matrix 8058 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8059 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8060 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8061 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8062 always used. 8063 8064 Output Parameters: 8065 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8066 . 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 8067 . ja - the column indices, use `NULL` if not needed 8068 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8069 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8070 8071 Level: developer 8072 8073 Notes: 8074 You CANNOT change any of the ia[] or ja[] values. 8075 8076 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8077 8078 Fortran Notes: 8079 Use 8080 .vb 8081 PetscInt, pointer :: ia(:),ja(:) 8082 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8083 ! Access the ith and jth entries via ia(i) and ja(j) 8084 .ve 8085 8086 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8087 @*/ 8088 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8089 { 8090 PetscFunctionBegin; 8091 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8092 PetscValidType(mat, 1); 8093 if (n) PetscAssertPointer(n, 5); 8094 if (ia) PetscAssertPointer(ia, 6); 8095 if (ja) PetscAssertPointer(ja, 7); 8096 if (done) PetscAssertPointer(done, 8); 8097 MatCheckPreallocated(mat, 1); 8098 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8099 else { 8100 if (done) *done = PETSC_TRUE; 8101 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8102 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8103 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8104 } 8105 PetscFunctionReturn(PETSC_SUCCESS); 8106 } 8107 8108 /*@C 8109 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8110 8111 Collective 8112 8113 Input Parameters: 8114 + mat - the matrix 8115 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8116 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8117 symmetrized 8118 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8119 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8120 always used. 8121 . n - number of columns in the (possibly compressed) matrix 8122 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8123 - ja - the row indices 8124 8125 Output Parameter: 8126 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8127 8128 Level: developer 8129 8130 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8131 @*/ 8132 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8133 { 8134 PetscFunctionBegin; 8135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8136 PetscValidType(mat, 1); 8137 PetscAssertPointer(n, 5); 8138 if (ia) PetscAssertPointer(ia, 6); 8139 if (ja) PetscAssertPointer(ja, 7); 8140 PetscAssertPointer(done, 8); 8141 MatCheckPreallocated(mat, 1); 8142 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8143 else { 8144 *done = PETSC_TRUE; 8145 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8146 } 8147 PetscFunctionReturn(PETSC_SUCCESS); 8148 } 8149 8150 /*@C 8151 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8152 8153 Collective 8154 8155 Input Parameters: 8156 + mat - the matrix 8157 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8158 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8159 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8160 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8161 always used. 8162 . n - size of (possibly compressed) matrix 8163 . ia - the row pointers 8164 - ja - the column indices 8165 8166 Output Parameter: 8167 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8168 8169 Level: developer 8170 8171 Note: 8172 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8173 us of the array after it has been restored. If you pass `NULL`, it will 8174 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8175 8176 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8177 @*/ 8178 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8179 { 8180 PetscFunctionBegin; 8181 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8182 PetscValidType(mat, 1); 8183 if (ia) PetscAssertPointer(ia, 6); 8184 if (ja) PetscAssertPointer(ja, 7); 8185 if (done) PetscAssertPointer(done, 8); 8186 MatCheckPreallocated(mat, 1); 8187 8188 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8189 else { 8190 if (done) *done = PETSC_TRUE; 8191 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8192 if (n) *n = 0; 8193 if (ia) *ia = NULL; 8194 if (ja) *ja = NULL; 8195 } 8196 PetscFunctionReturn(PETSC_SUCCESS); 8197 } 8198 8199 /*@C 8200 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8201 8202 Collective 8203 8204 Input Parameters: 8205 + mat - the matrix 8206 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8207 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8208 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8209 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8210 always used. 8211 8212 Output Parameters: 8213 + n - size of (possibly compressed) matrix 8214 . ia - the column pointers 8215 . ja - the row indices 8216 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8217 8218 Level: developer 8219 8220 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8221 @*/ 8222 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8223 { 8224 PetscFunctionBegin; 8225 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8226 PetscValidType(mat, 1); 8227 if (ia) PetscAssertPointer(ia, 6); 8228 if (ja) PetscAssertPointer(ja, 7); 8229 PetscAssertPointer(done, 8); 8230 MatCheckPreallocated(mat, 1); 8231 8232 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8233 else { 8234 *done = PETSC_TRUE; 8235 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8236 if (n) *n = 0; 8237 if (ia) *ia = NULL; 8238 if (ja) *ja = NULL; 8239 } 8240 PetscFunctionReturn(PETSC_SUCCESS); 8241 } 8242 8243 /*@ 8244 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8245 `MatGetColumnIJ()`. 8246 8247 Collective 8248 8249 Input Parameters: 8250 + mat - the matrix 8251 . ncolors - maximum color value 8252 . n - number of entries in colorarray 8253 - colorarray - array indicating color for each column 8254 8255 Output Parameter: 8256 . iscoloring - coloring generated using colorarray information 8257 8258 Level: developer 8259 8260 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8261 @*/ 8262 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8263 { 8264 PetscFunctionBegin; 8265 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8266 PetscValidType(mat, 1); 8267 PetscAssertPointer(colorarray, 4); 8268 PetscAssertPointer(iscoloring, 5); 8269 MatCheckPreallocated(mat, 1); 8270 8271 if (!mat->ops->coloringpatch) { 8272 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8273 } else { 8274 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8275 } 8276 PetscFunctionReturn(PETSC_SUCCESS); 8277 } 8278 8279 /*@ 8280 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8281 8282 Logically Collective 8283 8284 Input Parameter: 8285 . mat - the factored matrix to be reset 8286 8287 Level: developer 8288 8289 Notes: 8290 This routine should be used only with factored matrices formed by in-place 8291 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8292 format). This option can save memory, for example, when solving nonlinear 8293 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8294 ILU(0) preconditioner. 8295 8296 One can specify in-place ILU(0) factorization by calling 8297 .vb 8298 PCType(pc,PCILU); 8299 PCFactorSeUseInPlace(pc); 8300 .ve 8301 or by using the options -pc_type ilu -pc_factor_in_place 8302 8303 In-place factorization ILU(0) can also be used as a local 8304 solver for the blocks within the block Jacobi or additive Schwarz 8305 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8306 for details on setting local solver options. 8307 8308 Most users should employ the `KSP` interface for linear solvers 8309 instead of working directly with matrix algebra routines such as this. 8310 See, e.g., `KSPCreate()`. 8311 8312 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8313 @*/ 8314 PetscErrorCode MatSetUnfactored(Mat mat) 8315 { 8316 PetscFunctionBegin; 8317 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8318 PetscValidType(mat, 1); 8319 MatCheckPreallocated(mat, 1); 8320 mat->factortype = MAT_FACTOR_NONE; 8321 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8322 PetscUseTypeMethod(mat, setunfactored); 8323 PetscFunctionReturn(PETSC_SUCCESS); 8324 } 8325 8326 /*@ 8327 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8328 as the original matrix. 8329 8330 Collective 8331 8332 Input Parameters: 8333 + mat - the original matrix 8334 . isrow - parallel `IS` containing the rows this processor should obtain 8335 . 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. 8336 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8337 8338 Output Parameter: 8339 . newmat - the new submatrix, of the same type as the original matrix 8340 8341 Level: advanced 8342 8343 Notes: 8344 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8345 8346 Some matrix types place restrictions on the row and column indices, such 8347 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; 8348 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8349 8350 The index sets may not have duplicate entries. 8351 8352 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8353 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8354 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8355 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8356 you are finished using it. 8357 8358 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8359 the input matrix. 8360 8361 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8362 8363 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8364 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8365 8366 Example usage: 8367 Consider the following 8x8 matrix with 34 non-zero values, that is 8368 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8369 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8370 as follows 8371 .vb 8372 1 2 0 | 0 3 0 | 0 4 8373 Proc0 0 5 6 | 7 0 0 | 8 0 8374 9 0 10 | 11 0 0 | 12 0 8375 ------------------------------------- 8376 13 0 14 | 15 16 17 | 0 0 8377 Proc1 0 18 0 | 19 20 21 | 0 0 8378 0 0 0 | 22 23 0 | 24 0 8379 ------------------------------------- 8380 Proc2 25 26 27 | 0 0 28 | 29 0 8381 30 0 0 | 31 32 33 | 0 34 8382 .ve 8383 8384 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8385 8386 .vb 8387 2 0 | 0 3 0 | 0 8388 Proc0 5 6 | 7 0 0 | 8 8389 ------------------------------- 8390 Proc1 18 0 | 19 20 21 | 0 8391 ------------------------------- 8392 Proc2 26 27 | 0 0 28 | 29 8393 0 0 | 31 32 33 | 0 8394 .ve 8395 8396 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8397 @*/ 8398 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8399 { 8400 PetscMPIInt size; 8401 Mat *local; 8402 IS iscoltmp; 8403 PetscBool flg; 8404 8405 PetscFunctionBegin; 8406 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8407 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8408 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8409 PetscAssertPointer(newmat, 5); 8410 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8411 PetscValidType(mat, 1); 8412 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8413 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8414 8415 MatCheckPreallocated(mat, 1); 8416 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8417 8418 if (!iscol || isrow == iscol) { 8419 PetscBool stride; 8420 PetscMPIInt grabentirematrix = 0, grab; 8421 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8422 if (stride) { 8423 PetscInt first, step, n, rstart, rend; 8424 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8425 if (step == 1) { 8426 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8427 if (rstart == first) { 8428 PetscCall(ISGetLocalSize(isrow, &n)); 8429 if (n == rend - rstart) grabentirematrix = 1; 8430 } 8431 } 8432 } 8433 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8434 if (grab) { 8435 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8436 if (cll == MAT_INITIAL_MATRIX) { 8437 *newmat = mat; 8438 PetscCall(PetscObjectReference((PetscObject)mat)); 8439 } 8440 PetscFunctionReturn(PETSC_SUCCESS); 8441 } 8442 } 8443 8444 if (!iscol) { 8445 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8446 } else { 8447 iscoltmp = iscol; 8448 } 8449 8450 /* if original matrix is on just one processor then use submatrix generated */ 8451 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8452 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8453 goto setproperties; 8454 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8455 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8456 *newmat = *local; 8457 PetscCall(PetscFree(local)); 8458 goto setproperties; 8459 } else if (!mat->ops->createsubmatrix) { 8460 /* Create a new matrix type that implements the operation using the full matrix */ 8461 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8462 switch (cll) { 8463 case MAT_INITIAL_MATRIX: 8464 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8465 break; 8466 case MAT_REUSE_MATRIX: 8467 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8468 break; 8469 default: 8470 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8471 } 8472 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8473 goto setproperties; 8474 } 8475 8476 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8477 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8478 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8479 8480 setproperties: 8481 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8482 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8483 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8484 } 8485 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8486 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8487 PetscFunctionReturn(PETSC_SUCCESS); 8488 } 8489 8490 /*@ 8491 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8492 8493 Not Collective 8494 8495 Input Parameters: 8496 + A - the matrix we wish to propagate options from 8497 - B - the matrix we wish to propagate options to 8498 8499 Level: beginner 8500 8501 Note: 8502 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8503 8504 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8505 @*/ 8506 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8507 { 8508 PetscFunctionBegin; 8509 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8510 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8511 B->symmetry_eternal = A->symmetry_eternal; 8512 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8513 B->symmetric = A->symmetric; 8514 B->structurally_symmetric = A->structurally_symmetric; 8515 B->spd = A->spd; 8516 B->hermitian = A->hermitian; 8517 PetscFunctionReturn(PETSC_SUCCESS); 8518 } 8519 8520 /*@ 8521 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8522 used during the assembly process to store values that belong to 8523 other processors. 8524 8525 Not Collective 8526 8527 Input Parameters: 8528 + mat - the matrix 8529 . size - the initial size of the stash. 8530 - bsize - the initial size of the block-stash(if used). 8531 8532 Options Database Keys: 8533 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8534 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8535 8536 Level: intermediate 8537 8538 Notes: 8539 The block-stash is used for values set with `MatSetValuesBlocked()` while 8540 the stash is used for values set with `MatSetValues()` 8541 8542 Run with the option -info and look for output of the form 8543 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8544 to determine the appropriate value, MM, to use for size and 8545 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8546 to determine the value, BMM to use for bsize 8547 8548 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8549 @*/ 8550 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8551 { 8552 PetscFunctionBegin; 8553 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8554 PetscValidType(mat, 1); 8555 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8556 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8557 PetscFunctionReturn(PETSC_SUCCESS); 8558 } 8559 8560 /*@ 8561 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8562 the matrix 8563 8564 Neighbor-wise Collective 8565 8566 Input Parameters: 8567 + A - the matrix 8568 . x - the vector to be multiplied by the interpolation operator 8569 - y - the vector to be added to the result 8570 8571 Output Parameter: 8572 . w - the resulting vector 8573 8574 Level: intermediate 8575 8576 Notes: 8577 `w` may be the same vector as `y`. 8578 8579 This allows one to use either the restriction or interpolation (its transpose) 8580 matrix to do the interpolation 8581 8582 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8583 @*/ 8584 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8585 { 8586 PetscInt M, N, Ny; 8587 8588 PetscFunctionBegin; 8589 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8590 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8591 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8592 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8593 PetscCall(MatGetSize(A, &M, &N)); 8594 PetscCall(VecGetSize(y, &Ny)); 8595 if (M == Ny) { 8596 PetscCall(MatMultAdd(A, x, y, w)); 8597 } else { 8598 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8599 } 8600 PetscFunctionReturn(PETSC_SUCCESS); 8601 } 8602 8603 /*@ 8604 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8605 the matrix 8606 8607 Neighbor-wise Collective 8608 8609 Input Parameters: 8610 + A - the matrix 8611 - x - the vector to be interpolated 8612 8613 Output Parameter: 8614 . y - the resulting vector 8615 8616 Level: intermediate 8617 8618 Note: 8619 This allows one to use either the restriction or interpolation (its transpose) 8620 matrix to do the interpolation 8621 8622 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8623 @*/ 8624 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8625 { 8626 PetscInt M, N, Ny; 8627 8628 PetscFunctionBegin; 8629 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8630 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8631 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8632 PetscCall(MatGetSize(A, &M, &N)); 8633 PetscCall(VecGetSize(y, &Ny)); 8634 if (M == Ny) { 8635 PetscCall(MatMult(A, x, y)); 8636 } else { 8637 PetscCall(MatMultTranspose(A, x, y)); 8638 } 8639 PetscFunctionReturn(PETSC_SUCCESS); 8640 } 8641 8642 /*@ 8643 MatRestrict - $y = A*x$ or $A^T*x$ 8644 8645 Neighbor-wise Collective 8646 8647 Input Parameters: 8648 + A - the matrix 8649 - x - the vector to be restricted 8650 8651 Output Parameter: 8652 . y - the resulting vector 8653 8654 Level: intermediate 8655 8656 Note: 8657 This allows one to use either the restriction or interpolation (its transpose) 8658 matrix to do the restriction 8659 8660 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8661 @*/ 8662 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8663 { 8664 PetscInt M, N, Nx; 8665 8666 PetscFunctionBegin; 8667 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8668 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8669 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8670 PetscCall(MatGetSize(A, &M, &N)); 8671 PetscCall(VecGetSize(x, &Nx)); 8672 if (M == Nx) { 8673 PetscCall(MatMultTranspose(A, x, y)); 8674 } else { 8675 PetscCall(MatMult(A, x, y)); 8676 } 8677 PetscFunctionReturn(PETSC_SUCCESS); 8678 } 8679 8680 /*@ 8681 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8682 8683 Neighbor-wise Collective 8684 8685 Input Parameters: 8686 + A - the matrix 8687 . x - the input dense matrix to be multiplied 8688 - w - the input dense matrix to be added to the result 8689 8690 Output Parameter: 8691 . y - the output dense matrix 8692 8693 Level: intermediate 8694 8695 Note: 8696 This allows one to use either the restriction or interpolation (its transpose) 8697 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8698 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8699 8700 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8701 @*/ 8702 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8703 { 8704 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8705 PetscBool trans = PETSC_TRUE; 8706 MatReuse reuse = MAT_INITIAL_MATRIX; 8707 8708 PetscFunctionBegin; 8709 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8710 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8711 PetscValidType(x, 2); 8712 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8713 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8714 PetscCall(MatGetSize(A, &M, &N)); 8715 PetscCall(MatGetSize(x, &Mx, &Nx)); 8716 if (N == Mx) trans = PETSC_FALSE; 8717 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); 8718 Mo = trans ? N : M; 8719 if (*y) { 8720 PetscCall(MatGetSize(*y, &My, &Ny)); 8721 if (Mo == My && Nx == Ny) { 8722 reuse = MAT_REUSE_MATRIX; 8723 } else { 8724 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); 8725 PetscCall(MatDestroy(y)); 8726 } 8727 } 8728 8729 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8730 PetscBool flg; 8731 8732 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8733 if (w) { 8734 PetscInt My, Ny, Mw, Nw; 8735 8736 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8737 PetscCall(MatGetSize(*y, &My, &Ny)); 8738 PetscCall(MatGetSize(w, &Mw, &Nw)); 8739 if (!flg || My != Mw || Ny != Nw) w = NULL; 8740 } 8741 if (!w) { 8742 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8743 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8744 PetscCall(PetscObjectDereference((PetscObject)w)); 8745 } else { 8746 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8747 } 8748 } 8749 if (!trans) { 8750 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8751 } else { 8752 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8753 } 8754 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8755 PetscFunctionReturn(PETSC_SUCCESS); 8756 } 8757 8758 /*@ 8759 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8760 8761 Neighbor-wise Collective 8762 8763 Input Parameters: 8764 + A - the matrix 8765 - x - the input dense matrix 8766 8767 Output Parameter: 8768 . y - the output dense matrix 8769 8770 Level: intermediate 8771 8772 Note: 8773 This allows one to use either the restriction or interpolation (its transpose) 8774 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8775 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8776 8777 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8778 @*/ 8779 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8780 { 8781 PetscFunctionBegin; 8782 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8783 PetscFunctionReturn(PETSC_SUCCESS); 8784 } 8785 8786 /*@ 8787 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8788 8789 Neighbor-wise Collective 8790 8791 Input Parameters: 8792 + A - the matrix 8793 - x - the input dense matrix 8794 8795 Output Parameter: 8796 . y - the output dense matrix 8797 8798 Level: intermediate 8799 8800 Note: 8801 This allows one to use either the restriction or interpolation (its transpose) 8802 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8803 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8804 8805 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8806 @*/ 8807 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8808 { 8809 PetscFunctionBegin; 8810 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8811 PetscFunctionReturn(PETSC_SUCCESS); 8812 } 8813 8814 /*@ 8815 MatGetNullSpace - retrieves the null space of a matrix. 8816 8817 Logically Collective 8818 8819 Input Parameters: 8820 + mat - the matrix 8821 - nullsp - the null space object 8822 8823 Level: developer 8824 8825 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8826 @*/ 8827 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8828 { 8829 PetscFunctionBegin; 8830 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8831 PetscAssertPointer(nullsp, 2); 8832 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8833 PetscFunctionReturn(PETSC_SUCCESS); 8834 } 8835 8836 /*@C 8837 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8838 8839 Logically Collective 8840 8841 Input Parameters: 8842 + n - the number of matrices 8843 - mat - the array of matrices 8844 8845 Output Parameters: 8846 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8847 8848 Level: developer 8849 8850 Note: 8851 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8852 8853 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8854 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8855 @*/ 8856 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8857 { 8858 PetscFunctionBegin; 8859 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8860 PetscAssertPointer(mat, 2); 8861 PetscAssertPointer(nullsp, 3); 8862 8863 PetscCall(PetscCalloc1(3 * n, nullsp)); 8864 for (PetscInt i = 0; i < n; i++) { 8865 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8866 (*nullsp)[i] = mat[i]->nullsp; 8867 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8868 (*nullsp)[n + i] = mat[i]->nearnullsp; 8869 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8870 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8871 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8872 } 8873 PetscFunctionReturn(PETSC_SUCCESS); 8874 } 8875 8876 /*@C 8877 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8878 8879 Logically Collective 8880 8881 Input Parameters: 8882 + n - the number of matrices 8883 . mat - the array of matrices 8884 - nullsp - an array of null spaces 8885 8886 Level: developer 8887 8888 Note: 8889 Call `MatGetNullSpaces()` to create `nullsp` 8890 8891 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8892 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8893 @*/ 8894 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8895 { 8896 PetscFunctionBegin; 8897 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8898 PetscAssertPointer(mat, 2); 8899 PetscAssertPointer(nullsp, 3); 8900 PetscAssertPointer(*nullsp, 3); 8901 8902 for (PetscInt i = 0; i < n; i++) { 8903 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8904 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8905 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8906 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8907 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8908 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8909 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8910 } 8911 PetscCall(PetscFree(*nullsp)); 8912 PetscFunctionReturn(PETSC_SUCCESS); 8913 } 8914 8915 /*@ 8916 MatSetNullSpace - attaches a null space to a matrix. 8917 8918 Logically Collective 8919 8920 Input Parameters: 8921 + mat - the matrix 8922 - nullsp - the null space object 8923 8924 Level: advanced 8925 8926 Notes: 8927 This null space is used by the `KSP` linear solvers to solve singular systems. 8928 8929 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` 8930 8931 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 8932 to zero but the linear system will still be solved in a least squares sense. 8933 8934 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8935 the domain of a matrix A (from $R^n$ to $R^m$ (m rows, n columns) $R^n$ = the direct sum of the null space of A, n(A), + the range of $A^T$, $R(A^T)$. 8936 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 8937 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 8938 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$). 8939 This \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 8940 8941 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called 8942 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 8943 routine also automatically calls `MatSetTransposeNullSpace()`. 8944 8945 The user should call `MatNullSpaceDestroy()`. 8946 8947 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 8948 `KSPSetPCSide()` 8949 @*/ 8950 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 8951 { 8952 PetscFunctionBegin; 8953 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8954 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 8955 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 8956 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 8957 mat->nullsp = nullsp; 8958 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 8959 PetscFunctionReturn(PETSC_SUCCESS); 8960 } 8961 8962 /*@ 8963 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 8964 8965 Logically Collective 8966 8967 Input Parameters: 8968 + mat - the matrix 8969 - nullsp - the null space object 8970 8971 Level: developer 8972 8973 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 8974 @*/ 8975 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 8976 { 8977 PetscFunctionBegin; 8978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8979 PetscValidType(mat, 1); 8980 PetscAssertPointer(nullsp, 2); 8981 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 8982 PetscFunctionReturn(PETSC_SUCCESS); 8983 } 8984 8985 /*@ 8986 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 8987 8988 Logically Collective 8989 8990 Input Parameters: 8991 + mat - the matrix 8992 - nullsp - the null space object 8993 8994 Level: advanced 8995 8996 Notes: 8997 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 8998 8999 See `MatSetNullSpace()` 9000 9001 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9002 @*/ 9003 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9004 { 9005 PetscFunctionBegin; 9006 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9007 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9008 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9009 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9010 mat->transnullsp = nullsp; 9011 PetscFunctionReturn(PETSC_SUCCESS); 9012 } 9013 9014 /*@ 9015 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9016 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9017 9018 Logically Collective 9019 9020 Input Parameters: 9021 + mat - the matrix 9022 - nullsp - the null space object 9023 9024 Level: advanced 9025 9026 Notes: 9027 Overwrites any previous near null space that may have been attached 9028 9029 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9030 9031 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9032 @*/ 9033 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9034 { 9035 PetscFunctionBegin; 9036 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9037 PetscValidType(mat, 1); 9038 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9039 MatCheckPreallocated(mat, 1); 9040 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9041 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9042 mat->nearnullsp = nullsp; 9043 PetscFunctionReturn(PETSC_SUCCESS); 9044 } 9045 9046 /*@ 9047 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9048 9049 Not Collective 9050 9051 Input Parameter: 9052 . mat - the matrix 9053 9054 Output Parameter: 9055 . nullsp - the null space object, `NULL` if not set 9056 9057 Level: advanced 9058 9059 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9060 @*/ 9061 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9062 { 9063 PetscFunctionBegin; 9064 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9065 PetscValidType(mat, 1); 9066 PetscAssertPointer(nullsp, 2); 9067 MatCheckPreallocated(mat, 1); 9068 *nullsp = mat->nearnullsp; 9069 PetscFunctionReturn(PETSC_SUCCESS); 9070 } 9071 9072 /*@ 9073 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9074 9075 Collective 9076 9077 Input Parameters: 9078 + mat - the matrix 9079 . row - row/column permutation 9080 - info - information on desired factorization process 9081 9082 Level: developer 9083 9084 Notes: 9085 Probably really in-place only when level of fill is zero, otherwise allocates 9086 new space to store factored matrix and deletes previous memory. 9087 9088 Most users should employ the `KSP` interface for linear solvers 9089 instead of working directly with matrix algebra routines such as this. 9090 See, e.g., `KSPCreate()`. 9091 9092 Developer Note: 9093 The Fortran interface is not autogenerated as the 9094 interface definition cannot be generated correctly [due to `MatFactorInfo`] 9095 9096 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9097 @*/ 9098 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9099 { 9100 PetscFunctionBegin; 9101 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9102 PetscValidType(mat, 1); 9103 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9104 PetscAssertPointer(info, 3); 9105 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9106 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9107 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9108 MatCheckPreallocated(mat, 1); 9109 PetscUseTypeMethod(mat, iccfactor, row, info); 9110 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9111 PetscFunctionReturn(PETSC_SUCCESS); 9112 } 9113 9114 /*@ 9115 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9116 ghosted ones. 9117 9118 Not Collective 9119 9120 Input Parameters: 9121 + mat - the matrix 9122 - diag - the diagonal values, including ghost ones 9123 9124 Level: developer 9125 9126 Notes: 9127 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9128 9129 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9130 9131 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9132 @*/ 9133 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9134 { 9135 PetscMPIInt size; 9136 9137 PetscFunctionBegin; 9138 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9139 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9140 PetscValidType(mat, 1); 9141 9142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9143 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9144 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9145 if (size == 1) { 9146 PetscInt n, m; 9147 PetscCall(VecGetSize(diag, &n)); 9148 PetscCall(MatGetSize(mat, NULL, &m)); 9149 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9150 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9151 } else { 9152 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9153 } 9154 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9155 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9156 PetscFunctionReturn(PETSC_SUCCESS); 9157 } 9158 9159 /*@ 9160 MatGetInertia - Gets the inertia from a factored matrix 9161 9162 Collective 9163 9164 Input Parameter: 9165 . mat - the matrix 9166 9167 Output Parameters: 9168 + nneg - number of negative eigenvalues 9169 . nzero - number of zero eigenvalues 9170 - npos - number of positive eigenvalues 9171 9172 Level: advanced 9173 9174 Note: 9175 Matrix must have been factored by `MatCholeskyFactor()` 9176 9177 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9178 @*/ 9179 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9180 { 9181 PetscFunctionBegin; 9182 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9183 PetscValidType(mat, 1); 9184 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9185 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9186 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9187 PetscFunctionReturn(PETSC_SUCCESS); 9188 } 9189 9190 /*@C 9191 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9192 9193 Neighbor-wise Collective 9194 9195 Input Parameters: 9196 + mat - the factored matrix obtained with `MatGetFactor()` 9197 - b - the right-hand-side vectors 9198 9199 Output Parameter: 9200 . x - the result vectors 9201 9202 Level: developer 9203 9204 Note: 9205 The vectors `b` and `x` cannot be the same. I.e., one cannot 9206 call `MatSolves`(A,x,x). 9207 9208 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9209 @*/ 9210 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9211 { 9212 PetscFunctionBegin; 9213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9214 PetscValidType(mat, 1); 9215 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9216 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9217 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9218 9219 MatCheckPreallocated(mat, 1); 9220 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9221 PetscUseTypeMethod(mat, solves, b, x); 9222 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9223 PetscFunctionReturn(PETSC_SUCCESS); 9224 } 9225 9226 /*@ 9227 MatIsSymmetric - Test whether a matrix is symmetric 9228 9229 Collective 9230 9231 Input Parameters: 9232 + A - the matrix to test 9233 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9234 9235 Output Parameter: 9236 . flg - the result 9237 9238 Level: intermediate 9239 9240 Notes: 9241 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9242 9243 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9244 9245 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9246 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9247 9248 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9249 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9250 @*/ 9251 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9252 { 9253 PetscFunctionBegin; 9254 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9255 PetscAssertPointer(flg, 3); 9256 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9257 else { 9258 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9259 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9260 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9261 } 9262 PetscFunctionReturn(PETSC_SUCCESS); 9263 } 9264 9265 /*@ 9266 MatIsHermitian - Test whether a matrix is Hermitian 9267 9268 Collective 9269 9270 Input Parameters: 9271 + A - the matrix to test 9272 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9273 9274 Output Parameter: 9275 . flg - the result 9276 9277 Level: intermediate 9278 9279 Notes: 9280 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9281 9282 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9283 9284 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9285 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9286 9287 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9288 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9289 @*/ 9290 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9291 { 9292 PetscFunctionBegin; 9293 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9294 PetscAssertPointer(flg, 3); 9295 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9296 else { 9297 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9298 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9299 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9300 } 9301 PetscFunctionReturn(PETSC_SUCCESS); 9302 } 9303 9304 /*@ 9305 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9306 9307 Not Collective 9308 9309 Input Parameter: 9310 . A - the matrix to check 9311 9312 Output Parameters: 9313 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9314 - flg - the result (only valid if set is `PETSC_TRUE`) 9315 9316 Level: advanced 9317 9318 Notes: 9319 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9320 if you want it explicitly checked 9321 9322 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9323 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9324 9325 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9326 @*/ 9327 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9328 { 9329 PetscFunctionBegin; 9330 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9331 PetscAssertPointer(set, 2); 9332 PetscAssertPointer(flg, 3); 9333 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9334 *set = PETSC_TRUE; 9335 *flg = PetscBool3ToBool(A->symmetric); 9336 } else { 9337 *set = PETSC_FALSE; 9338 } 9339 PetscFunctionReturn(PETSC_SUCCESS); 9340 } 9341 9342 /*@ 9343 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9344 9345 Not Collective 9346 9347 Input Parameter: 9348 . A - the matrix to check 9349 9350 Output Parameters: 9351 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9352 - flg - the result (only valid if set is `PETSC_TRUE`) 9353 9354 Level: advanced 9355 9356 Notes: 9357 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9358 9359 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9360 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9361 9362 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9363 @*/ 9364 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9365 { 9366 PetscFunctionBegin; 9367 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9368 PetscAssertPointer(set, 2); 9369 PetscAssertPointer(flg, 3); 9370 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9371 *set = PETSC_TRUE; 9372 *flg = PetscBool3ToBool(A->spd); 9373 } else { 9374 *set = PETSC_FALSE; 9375 } 9376 PetscFunctionReturn(PETSC_SUCCESS); 9377 } 9378 9379 /*@ 9380 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9381 9382 Not Collective 9383 9384 Input Parameter: 9385 . A - the matrix to check 9386 9387 Output Parameters: 9388 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9389 - flg - the result (only valid if set is `PETSC_TRUE`) 9390 9391 Level: advanced 9392 9393 Notes: 9394 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9395 if you want it explicitly checked 9396 9397 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9398 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9399 9400 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9401 @*/ 9402 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9403 { 9404 PetscFunctionBegin; 9405 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9406 PetscAssertPointer(set, 2); 9407 PetscAssertPointer(flg, 3); 9408 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9409 *set = PETSC_TRUE; 9410 *flg = PetscBool3ToBool(A->hermitian); 9411 } else { 9412 *set = PETSC_FALSE; 9413 } 9414 PetscFunctionReturn(PETSC_SUCCESS); 9415 } 9416 9417 /*@ 9418 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9419 9420 Collective 9421 9422 Input Parameter: 9423 . A - the matrix to test 9424 9425 Output Parameter: 9426 . flg - the result 9427 9428 Level: intermediate 9429 9430 Notes: 9431 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9432 9433 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 9434 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9435 9436 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9437 @*/ 9438 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9439 { 9440 PetscFunctionBegin; 9441 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9442 PetscAssertPointer(flg, 2); 9443 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9444 *flg = PetscBool3ToBool(A->structurally_symmetric); 9445 } else { 9446 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9447 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9448 } 9449 PetscFunctionReturn(PETSC_SUCCESS); 9450 } 9451 9452 /*@ 9453 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9454 9455 Not Collective 9456 9457 Input Parameter: 9458 . A - the matrix to check 9459 9460 Output Parameters: 9461 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9462 - flg - the result (only valid if set is PETSC_TRUE) 9463 9464 Level: advanced 9465 9466 Notes: 9467 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 9468 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9469 9470 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9471 9472 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9473 @*/ 9474 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9475 { 9476 PetscFunctionBegin; 9477 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9478 PetscAssertPointer(set, 2); 9479 PetscAssertPointer(flg, 3); 9480 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9481 *set = PETSC_TRUE; 9482 *flg = PetscBool3ToBool(A->structurally_symmetric); 9483 } else { 9484 *set = PETSC_FALSE; 9485 } 9486 PetscFunctionReturn(PETSC_SUCCESS); 9487 } 9488 9489 /*@ 9490 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9491 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9492 9493 Not Collective 9494 9495 Input Parameter: 9496 . mat - the matrix 9497 9498 Output Parameters: 9499 + nstash - the size of the stash 9500 . reallocs - the number of additional mallocs incurred. 9501 . bnstash - the size of the block stash 9502 - breallocs - the number of additional mallocs incurred.in the block stash 9503 9504 Level: advanced 9505 9506 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9507 @*/ 9508 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9509 { 9510 PetscFunctionBegin; 9511 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9512 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9513 PetscFunctionReturn(PETSC_SUCCESS); 9514 } 9515 9516 /*@ 9517 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9518 parallel layout, `PetscLayout` for rows and columns 9519 9520 Collective 9521 9522 Input Parameter: 9523 . mat - the matrix 9524 9525 Output Parameters: 9526 + right - (optional) vector that the matrix can be multiplied against 9527 - left - (optional) vector that the matrix vector product can be stored in 9528 9529 Level: advanced 9530 9531 Notes: 9532 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()`. 9533 9534 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9535 9536 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9537 @*/ 9538 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9539 { 9540 PetscFunctionBegin; 9541 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9542 PetscValidType(mat, 1); 9543 if (mat->ops->getvecs) { 9544 PetscUseTypeMethod(mat, getvecs, right, left); 9545 } else { 9546 if (right) { 9547 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9548 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9549 PetscCall(VecSetType(*right, mat->defaultvectype)); 9550 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9551 if (mat->boundtocpu && mat->bindingpropagates) { 9552 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9553 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9554 } 9555 #endif 9556 } 9557 if (left) { 9558 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9559 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9560 PetscCall(VecSetType(*left, mat->defaultvectype)); 9561 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9562 if (mat->boundtocpu && mat->bindingpropagates) { 9563 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9564 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9565 } 9566 #endif 9567 } 9568 } 9569 PetscFunctionReturn(PETSC_SUCCESS); 9570 } 9571 9572 /*@ 9573 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9574 with default values. 9575 9576 Not Collective 9577 9578 Input Parameter: 9579 . info - the `MatFactorInfo` data structure 9580 9581 Level: developer 9582 9583 Notes: 9584 The solvers are generally used through the `KSP` and `PC` objects, for example 9585 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9586 9587 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9588 9589 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9590 @*/ 9591 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9592 { 9593 PetscFunctionBegin; 9594 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9595 PetscFunctionReturn(PETSC_SUCCESS); 9596 } 9597 9598 /*@ 9599 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9600 9601 Collective 9602 9603 Input Parameters: 9604 + mat - the factored matrix 9605 - is - the index set defining the Schur indices (0-based) 9606 9607 Level: advanced 9608 9609 Notes: 9610 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9611 9612 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9613 9614 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9615 9616 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9617 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9618 @*/ 9619 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9620 { 9621 PetscErrorCode (*f)(Mat, IS); 9622 9623 PetscFunctionBegin; 9624 PetscValidType(mat, 1); 9625 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9626 PetscValidType(is, 2); 9627 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9628 PetscCheckSameComm(mat, 1, is, 2); 9629 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9630 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9631 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9632 PetscCall(MatDestroy(&mat->schur)); 9633 PetscCall((*f)(mat, is)); 9634 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9635 PetscFunctionReturn(PETSC_SUCCESS); 9636 } 9637 9638 /*@ 9639 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9640 9641 Logically Collective 9642 9643 Input Parameters: 9644 + F - the factored matrix obtained by calling `MatGetFactor()` 9645 . S - location where to return the Schur complement, can be `NULL` 9646 - status - the status of the Schur complement matrix, can be `NULL` 9647 9648 Level: advanced 9649 9650 Notes: 9651 You must call `MatFactorSetSchurIS()` before calling this routine. 9652 9653 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9654 9655 The routine provides a copy of the Schur matrix stored within the solver data structures. 9656 The caller must destroy the object when it is no longer needed. 9657 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9658 9659 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) 9660 9661 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9662 9663 Developer Note: 9664 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9665 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9666 9667 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9668 @*/ 9669 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9670 { 9671 PetscFunctionBegin; 9672 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9673 if (S) PetscAssertPointer(S, 2); 9674 if (status) PetscAssertPointer(status, 3); 9675 if (S) { 9676 PetscErrorCode (*f)(Mat, Mat *); 9677 9678 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9679 if (f) { 9680 PetscCall((*f)(F, S)); 9681 } else { 9682 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9683 } 9684 } 9685 if (status) *status = F->schur_status; 9686 PetscFunctionReturn(PETSC_SUCCESS); 9687 } 9688 9689 /*@ 9690 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9691 9692 Logically Collective 9693 9694 Input Parameters: 9695 + F - the factored matrix obtained by calling `MatGetFactor()` 9696 . S - location where to return the Schur complement, can be `NULL` 9697 - status - the status of the Schur complement matrix, can be `NULL` 9698 9699 Level: advanced 9700 9701 Notes: 9702 You must call `MatFactorSetSchurIS()` before calling this routine. 9703 9704 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9705 9706 The routine returns a the Schur Complement stored within the data structures of the solver. 9707 9708 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9709 9710 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9711 9712 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9713 9714 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9715 9716 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9717 @*/ 9718 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9719 { 9720 PetscFunctionBegin; 9721 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9722 if (S) { 9723 PetscAssertPointer(S, 2); 9724 *S = F->schur; 9725 } 9726 if (status) { 9727 PetscAssertPointer(status, 3); 9728 *status = F->schur_status; 9729 } 9730 PetscFunctionReturn(PETSC_SUCCESS); 9731 } 9732 9733 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9734 { 9735 Mat S = F->schur; 9736 9737 PetscFunctionBegin; 9738 switch (F->schur_status) { 9739 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9740 case MAT_FACTOR_SCHUR_INVERTED: 9741 if (S) { 9742 S->ops->solve = NULL; 9743 S->ops->matsolve = NULL; 9744 S->ops->solvetranspose = NULL; 9745 S->ops->matsolvetranspose = NULL; 9746 S->ops->solveadd = NULL; 9747 S->ops->solvetransposeadd = NULL; 9748 S->factortype = MAT_FACTOR_NONE; 9749 PetscCall(PetscFree(S->solvertype)); 9750 } 9751 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9752 break; 9753 default: 9754 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9755 } 9756 PetscFunctionReturn(PETSC_SUCCESS); 9757 } 9758 9759 /*@ 9760 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9761 9762 Logically Collective 9763 9764 Input Parameters: 9765 + F - the factored matrix obtained by calling `MatGetFactor()` 9766 . S - location where the Schur complement is stored 9767 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9768 9769 Level: advanced 9770 9771 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9772 @*/ 9773 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9774 { 9775 PetscFunctionBegin; 9776 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9777 if (S) { 9778 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9779 *S = NULL; 9780 } 9781 F->schur_status = status; 9782 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9783 PetscFunctionReturn(PETSC_SUCCESS); 9784 } 9785 9786 /*@ 9787 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9788 9789 Logically Collective 9790 9791 Input Parameters: 9792 + F - the factored matrix obtained by calling `MatGetFactor()` 9793 . rhs - location where the right-hand side of the Schur complement system is stored 9794 - sol - location where the solution of the Schur complement system has to be returned 9795 9796 Level: advanced 9797 9798 Notes: 9799 The sizes of the vectors should match the size of the Schur complement 9800 9801 Must be called after `MatFactorSetSchurIS()` 9802 9803 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9804 @*/ 9805 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9806 { 9807 PetscFunctionBegin; 9808 PetscValidType(F, 1); 9809 PetscValidType(rhs, 2); 9810 PetscValidType(sol, 3); 9811 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9812 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9813 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9814 PetscCheckSameComm(F, 1, rhs, 2); 9815 PetscCheckSameComm(F, 1, sol, 3); 9816 PetscCall(MatFactorFactorizeSchurComplement(F)); 9817 switch (F->schur_status) { 9818 case MAT_FACTOR_SCHUR_FACTORED: 9819 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9820 break; 9821 case MAT_FACTOR_SCHUR_INVERTED: 9822 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9823 break; 9824 default: 9825 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9826 } 9827 PetscFunctionReturn(PETSC_SUCCESS); 9828 } 9829 9830 /*@ 9831 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9832 9833 Logically Collective 9834 9835 Input Parameters: 9836 + F - the factored matrix obtained by calling `MatGetFactor()` 9837 . rhs - location where the right-hand side of the Schur complement system is stored 9838 - sol - location where the solution of the Schur complement system has to be returned 9839 9840 Level: advanced 9841 9842 Notes: 9843 The sizes of the vectors should match the size of the Schur complement 9844 9845 Must be called after `MatFactorSetSchurIS()` 9846 9847 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9848 @*/ 9849 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9850 { 9851 PetscFunctionBegin; 9852 PetscValidType(F, 1); 9853 PetscValidType(rhs, 2); 9854 PetscValidType(sol, 3); 9855 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9856 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9857 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9858 PetscCheckSameComm(F, 1, rhs, 2); 9859 PetscCheckSameComm(F, 1, sol, 3); 9860 PetscCall(MatFactorFactorizeSchurComplement(F)); 9861 switch (F->schur_status) { 9862 case MAT_FACTOR_SCHUR_FACTORED: 9863 PetscCall(MatSolve(F->schur, rhs, sol)); 9864 break; 9865 case MAT_FACTOR_SCHUR_INVERTED: 9866 PetscCall(MatMult(F->schur, rhs, sol)); 9867 break; 9868 default: 9869 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9870 } 9871 PetscFunctionReturn(PETSC_SUCCESS); 9872 } 9873 9874 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9875 #if PetscDefined(HAVE_CUDA) 9876 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9877 #endif 9878 9879 /* Schur status updated in the interface */ 9880 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9881 { 9882 Mat S = F->schur; 9883 9884 PetscFunctionBegin; 9885 if (S) { 9886 PetscMPIInt size; 9887 PetscBool isdense, isdensecuda; 9888 9889 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9890 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9891 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9892 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9893 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9894 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9895 if (isdense) { 9896 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9897 } else if (isdensecuda) { 9898 #if defined(PETSC_HAVE_CUDA) 9899 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9900 #endif 9901 } 9902 // HIP?????????????? 9903 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9904 } 9905 PetscFunctionReturn(PETSC_SUCCESS); 9906 } 9907 9908 /*@ 9909 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9910 9911 Logically Collective 9912 9913 Input Parameter: 9914 . F - the factored matrix obtained by calling `MatGetFactor()` 9915 9916 Level: advanced 9917 9918 Notes: 9919 Must be called after `MatFactorSetSchurIS()`. 9920 9921 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9922 9923 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9924 @*/ 9925 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9926 { 9927 PetscFunctionBegin; 9928 PetscValidType(F, 1); 9929 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9930 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9931 PetscCall(MatFactorFactorizeSchurComplement(F)); 9932 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9933 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9934 PetscFunctionReturn(PETSC_SUCCESS); 9935 } 9936 9937 /*@ 9938 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 9939 9940 Logically Collective 9941 9942 Input Parameter: 9943 . F - the factored matrix obtained by calling `MatGetFactor()` 9944 9945 Level: advanced 9946 9947 Note: 9948 Must be called after `MatFactorSetSchurIS()` 9949 9950 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 9951 @*/ 9952 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 9953 { 9954 MatFactorInfo info; 9955 9956 PetscFunctionBegin; 9957 PetscValidType(F, 1); 9958 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9959 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 9960 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 9961 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 9962 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 9963 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 9964 } else { 9965 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 9966 } 9967 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 9968 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 9969 PetscFunctionReturn(PETSC_SUCCESS); 9970 } 9971 9972 /*@ 9973 MatPtAP - Creates the matrix product $C = P^T * A * P$ 9974 9975 Neighbor-wise Collective 9976 9977 Input Parameters: 9978 + A - the matrix 9979 . P - the projection matrix 9980 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 9981 - 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 9982 if the result is a dense matrix this is irrelevant 9983 9984 Output Parameter: 9985 . C - the product matrix 9986 9987 Level: intermediate 9988 9989 Notes: 9990 C will be created and must be destroyed by the user with `MatDestroy()`. 9991 9992 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 9993 9994 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 9995 9996 Developer Note: 9997 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 9998 9999 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10000 @*/ 10001 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10002 { 10003 PetscFunctionBegin; 10004 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10005 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10006 10007 if (scall == MAT_INITIAL_MATRIX) { 10008 PetscCall(MatProductCreate(A, P, NULL, C)); 10009 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10010 PetscCall(MatProductSetAlgorithm(*C, "default")); 10011 PetscCall(MatProductSetFill(*C, fill)); 10012 10013 (*C)->product->api_user = PETSC_TRUE; 10014 PetscCall(MatProductSetFromOptions(*C)); 10015 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); 10016 PetscCall(MatProductSymbolic(*C)); 10017 } else { /* scall == MAT_REUSE_MATRIX */ 10018 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10019 } 10020 10021 PetscCall(MatProductNumeric(*C)); 10022 (*C)->symmetric = A->symmetric; 10023 (*C)->spd = A->spd; 10024 PetscFunctionReturn(PETSC_SUCCESS); 10025 } 10026 10027 /*@ 10028 MatRARt - Creates the matrix product $C = R * A * R^T$ 10029 10030 Neighbor-wise Collective 10031 10032 Input Parameters: 10033 + A - the matrix 10034 . R - the projection matrix 10035 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10036 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10037 if the result is a dense matrix this is irrelevant 10038 10039 Output Parameter: 10040 . C - the product matrix 10041 10042 Level: intermediate 10043 10044 Notes: 10045 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10046 10047 An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done 10048 10049 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10050 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10051 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10052 We recommend using `MatPtAP()` when possible. 10053 10054 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10055 10056 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10057 @*/ 10058 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10059 { 10060 PetscFunctionBegin; 10061 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10062 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10063 10064 if (scall == MAT_INITIAL_MATRIX) { 10065 PetscCall(MatProductCreate(A, R, NULL, C)); 10066 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10067 PetscCall(MatProductSetAlgorithm(*C, "default")); 10068 PetscCall(MatProductSetFill(*C, fill)); 10069 10070 (*C)->product->api_user = PETSC_TRUE; 10071 PetscCall(MatProductSetFromOptions(*C)); 10072 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); 10073 PetscCall(MatProductSymbolic(*C)); 10074 } else { /* scall == MAT_REUSE_MATRIX */ 10075 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10076 } 10077 10078 PetscCall(MatProductNumeric(*C)); 10079 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10080 PetscFunctionReturn(PETSC_SUCCESS); 10081 } 10082 10083 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10084 { 10085 PetscBool flg = PETSC_TRUE; 10086 10087 PetscFunctionBegin; 10088 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10089 if (scall == MAT_INITIAL_MATRIX) { 10090 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10091 PetscCall(MatProductCreate(A, B, NULL, C)); 10092 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10093 PetscCall(MatProductSetFill(*C, fill)); 10094 } else { /* scall == MAT_REUSE_MATRIX */ 10095 Mat_Product *product = (*C)->product; 10096 10097 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10098 if (flg && product && product->type != ptype) { 10099 PetscCall(MatProductClear(*C)); 10100 product = NULL; 10101 } 10102 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10103 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10104 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10105 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10106 product = (*C)->product; 10107 product->fill = fill; 10108 product->clear = PETSC_TRUE; 10109 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10110 flg = PETSC_FALSE; 10111 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10112 } 10113 } 10114 if (flg) { 10115 (*C)->product->api_user = PETSC_TRUE; 10116 PetscCall(MatProductSetType(*C, ptype)); 10117 PetscCall(MatProductSetFromOptions(*C)); 10118 PetscCall(MatProductSymbolic(*C)); 10119 } 10120 PetscCall(MatProductNumeric(*C)); 10121 PetscFunctionReturn(PETSC_SUCCESS); 10122 } 10123 10124 /*@ 10125 MatMatMult - Performs matrix-matrix multiplication C=A*B. 10126 10127 Neighbor-wise Collective 10128 10129 Input Parameters: 10130 + A - the left matrix 10131 . B - the right matrix 10132 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10133 - 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 10134 if the result is a dense matrix this is irrelevant 10135 10136 Output Parameter: 10137 . C - the product matrix 10138 10139 Notes: 10140 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10141 10142 `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 10143 call to this function with `MAT_INITIAL_MATRIX`. 10144 10145 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10146 10147 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`, 10148 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10149 10150 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10151 10152 Example of Usage: 10153 .vb 10154 MatProductCreate(A,B,NULL,&C); 10155 MatProductSetType(C,MATPRODUCT_AB); 10156 MatProductSymbolic(C); 10157 MatProductNumeric(C); // compute C=A * B 10158 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10159 MatProductNumeric(C); 10160 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10161 MatProductNumeric(C); 10162 .ve 10163 10164 Level: intermediate 10165 10166 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10167 @*/ 10168 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10169 { 10170 PetscFunctionBegin; 10171 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10172 PetscFunctionReturn(PETSC_SUCCESS); 10173 } 10174 10175 /*@ 10176 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10177 10178 Neighbor-wise Collective 10179 10180 Input Parameters: 10181 + A - the left matrix 10182 . B - the right matrix 10183 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10184 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10185 10186 Output Parameter: 10187 . C - the product matrix 10188 10189 Options Database Key: 10190 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10191 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10192 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10193 10194 Level: intermediate 10195 10196 Notes: 10197 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10198 10199 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10200 10201 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10202 actually needed. 10203 10204 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10205 and for pairs of `MATMPIDENSE` matrices. 10206 10207 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt` 10208 10209 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10210 10211 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10212 @*/ 10213 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10214 { 10215 PetscFunctionBegin; 10216 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10217 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10218 PetscFunctionReturn(PETSC_SUCCESS); 10219 } 10220 10221 /*@ 10222 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10223 10224 Neighbor-wise Collective 10225 10226 Input Parameters: 10227 + A - the left matrix 10228 . B - the right matrix 10229 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10230 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10231 10232 Output Parameter: 10233 . C - the product matrix 10234 10235 Level: intermediate 10236 10237 Notes: 10238 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10239 10240 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call. 10241 10242 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB` 10243 10244 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10245 actually needed. 10246 10247 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10248 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10249 10250 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10251 10252 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10253 @*/ 10254 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10255 { 10256 PetscFunctionBegin; 10257 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10258 PetscFunctionReturn(PETSC_SUCCESS); 10259 } 10260 10261 /*@ 10262 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10263 10264 Neighbor-wise Collective 10265 10266 Input Parameters: 10267 + A - the left matrix 10268 . B - the middle matrix 10269 . C - the right matrix 10270 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10271 - 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 10272 if the result is a dense matrix this is irrelevant 10273 10274 Output Parameter: 10275 . D - the product matrix 10276 10277 Level: intermediate 10278 10279 Notes: 10280 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10281 10282 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10283 10284 This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC` 10285 10286 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10287 actually needed. 10288 10289 If you have many matrices with the same non-zero structure to multiply, you 10290 should use `MAT_REUSE_MATRIX` in all calls but the first 10291 10292 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10293 10294 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10295 @*/ 10296 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10297 { 10298 PetscFunctionBegin; 10299 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10300 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10301 10302 if (scall == MAT_INITIAL_MATRIX) { 10303 PetscCall(MatProductCreate(A, B, C, D)); 10304 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10305 PetscCall(MatProductSetAlgorithm(*D, "default")); 10306 PetscCall(MatProductSetFill(*D, fill)); 10307 10308 (*D)->product->api_user = PETSC_TRUE; 10309 PetscCall(MatProductSetFromOptions(*D)); 10310 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, 10311 ((PetscObject)C)->type_name); 10312 PetscCall(MatProductSymbolic(*D)); 10313 } else { /* user may change input matrices when REUSE */ 10314 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10315 } 10316 PetscCall(MatProductNumeric(*D)); 10317 PetscFunctionReturn(PETSC_SUCCESS); 10318 } 10319 10320 /*@ 10321 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10322 10323 Collective 10324 10325 Input Parameters: 10326 + mat - the matrix 10327 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10328 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10329 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10330 10331 Output Parameter: 10332 . matredundant - redundant matrix 10333 10334 Level: advanced 10335 10336 Notes: 10337 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10338 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10339 10340 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10341 calling it. 10342 10343 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10344 10345 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10346 @*/ 10347 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10348 { 10349 MPI_Comm comm; 10350 PetscMPIInt size; 10351 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10352 Mat_Redundant *redund = NULL; 10353 PetscSubcomm psubcomm = NULL; 10354 MPI_Comm subcomm_in = subcomm; 10355 Mat *matseq; 10356 IS isrow, iscol; 10357 PetscBool newsubcomm = PETSC_FALSE; 10358 10359 PetscFunctionBegin; 10360 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10361 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10362 PetscAssertPointer(*matredundant, 5); 10363 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10364 } 10365 10366 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10367 if (size == 1 || nsubcomm == 1) { 10368 if (reuse == MAT_INITIAL_MATRIX) { 10369 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10370 } else { 10371 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"); 10372 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10373 } 10374 PetscFunctionReturn(PETSC_SUCCESS); 10375 } 10376 10377 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10378 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10379 MatCheckPreallocated(mat, 1); 10380 10381 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10382 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10383 /* create psubcomm, then get subcomm */ 10384 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10385 PetscCallMPI(MPI_Comm_size(comm, &size)); 10386 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10387 10388 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10389 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10390 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10391 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10392 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10393 newsubcomm = PETSC_TRUE; 10394 PetscCall(PetscSubcommDestroy(&psubcomm)); 10395 } 10396 10397 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10398 if (reuse == MAT_INITIAL_MATRIX) { 10399 mloc_sub = PETSC_DECIDE; 10400 nloc_sub = PETSC_DECIDE; 10401 if (bs < 1) { 10402 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10403 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10404 } else { 10405 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10406 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10407 } 10408 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10409 rstart = rend - mloc_sub; 10410 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10411 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10412 PetscCall(ISSetIdentity(iscol)); 10413 } else { /* reuse == MAT_REUSE_MATRIX */ 10414 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"); 10415 /* retrieve subcomm */ 10416 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10417 redund = (*matredundant)->redundant; 10418 isrow = redund->isrow; 10419 iscol = redund->iscol; 10420 matseq = redund->matseq; 10421 } 10422 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10423 10424 /* get matredundant over subcomm */ 10425 if (reuse == MAT_INITIAL_MATRIX) { 10426 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10427 10428 /* create a supporting struct and attach it to C for reuse */ 10429 PetscCall(PetscNew(&redund)); 10430 (*matredundant)->redundant = redund; 10431 redund->isrow = isrow; 10432 redund->iscol = iscol; 10433 redund->matseq = matseq; 10434 if (newsubcomm) { 10435 redund->subcomm = subcomm; 10436 } else { 10437 redund->subcomm = MPI_COMM_NULL; 10438 } 10439 } else { 10440 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10441 } 10442 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10443 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10444 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10445 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10446 } 10447 #endif 10448 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10449 PetscFunctionReturn(PETSC_SUCCESS); 10450 } 10451 10452 /*@C 10453 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10454 a given `Mat`. Each submatrix can span multiple procs. 10455 10456 Collective 10457 10458 Input Parameters: 10459 + mat - the matrix 10460 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10461 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10462 10463 Output Parameter: 10464 . subMat - parallel sub-matrices each spanning a given `subcomm` 10465 10466 Level: advanced 10467 10468 Notes: 10469 The submatrix partition across processors is dictated by `subComm` a 10470 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10471 is not restricted to be grouped with consecutive original MPI processes. 10472 10473 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10474 map directly to the layout of the original matrix [wrt the local 10475 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10476 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10477 the `subMat`. However the offDiagMat looses some columns - and this is 10478 reconstructed with `MatSetValues()` 10479 10480 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10481 10482 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10483 @*/ 10484 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10485 { 10486 PetscMPIInt commsize, subCommSize; 10487 10488 PetscFunctionBegin; 10489 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10490 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10491 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10492 10493 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"); 10494 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10495 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10496 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10497 PetscFunctionReturn(PETSC_SUCCESS); 10498 } 10499 10500 /*@ 10501 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10502 10503 Not Collective 10504 10505 Input Parameters: 10506 + mat - matrix to extract local submatrix from 10507 . isrow - local row indices for submatrix 10508 - iscol - local column indices for submatrix 10509 10510 Output Parameter: 10511 . submat - the submatrix 10512 10513 Level: intermediate 10514 10515 Notes: 10516 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10517 10518 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10519 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10520 10521 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10522 `MatSetValuesBlockedLocal()` will also be implemented. 10523 10524 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10525 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10526 10527 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10528 @*/ 10529 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10530 { 10531 PetscFunctionBegin; 10532 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10533 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10534 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10535 PetscCheckSameComm(isrow, 2, iscol, 3); 10536 PetscAssertPointer(submat, 4); 10537 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10538 10539 if (mat->ops->getlocalsubmatrix) { 10540 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10541 } else { 10542 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10543 } 10544 PetscFunctionReturn(PETSC_SUCCESS); 10545 } 10546 10547 /*@ 10548 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10549 10550 Not Collective 10551 10552 Input Parameters: 10553 + mat - matrix to extract local submatrix from 10554 . isrow - local row indices for submatrix 10555 . iscol - local column indices for submatrix 10556 - submat - the submatrix 10557 10558 Level: intermediate 10559 10560 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10561 @*/ 10562 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10563 { 10564 PetscFunctionBegin; 10565 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10566 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10567 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10568 PetscCheckSameComm(isrow, 2, iscol, 3); 10569 PetscAssertPointer(submat, 4); 10570 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10571 10572 if (mat->ops->restorelocalsubmatrix) { 10573 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10574 } else { 10575 PetscCall(MatDestroy(submat)); 10576 } 10577 *submat = NULL; 10578 PetscFunctionReturn(PETSC_SUCCESS); 10579 } 10580 10581 /*@ 10582 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10583 10584 Collective 10585 10586 Input Parameter: 10587 . mat - the matrix 10588 10589 Output Parameter: 10590 . is - if any rows have zero diagonals this contains the list of them 10591 10592 Level: developer 10593 10594 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10595 @*/ 10596 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10597 { 10598 PetscFunctionBegin; 10599 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10600 PetscValidType(mat, 1); 10601 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10602 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10603 10604 if (!mat->ops->findzerodiagonals) { 10605 Vec diag; 10606 const PetscScalar *a; 10607 PetscInt *rows; 10608 PetscInt rStart, rEnd, r, nrow = 0; 10609 10610 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10611 PetscCall(MatGetDiagonal(mat, diag)); 10612 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10613 PetscCall(VecGetArrayRead(diag, &a)); 10614 for (r = 0; r < rEnd - rStart; ++r) 10615 if (a[r] == 0.0) ++nrow; 10616 PetscCall(PetscMalloc1(nrow, &rows)); 10617 nrow = 0; 10618 for (r = 0; r < rEnd - rStart; ++r) 10619 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10620 PetscCall(VecRestoreArrayRead(diag, &a)); 10621 PetscCall(VecDestroy(&diag)); 10622 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10623 } else { 10624 PetscUseTypeMethod(mat, findzerodiagonals, is); 10625 } 10626 PetscFunctionReturn(PETSC_SUCCESS); 10627 } 10628 10629 /*@ 10630 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10631 10632 Collective 10633 10634 Input Parameter: 10635 . mat - the matrix 10636 10637 Output Parameter: 10638 . is - contains the list of rows with off block diagonal entries 10639 10640 Level: developer 10641 10642 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10643 @*/ 10644 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10645 { 10646 PetscFunctionBegin; 10647 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10648 PetscValidType(mat, 1); 10649 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10650 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10651 10652 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10653 PetscFunctionReturn(PETSC_SUCCESS); 10654 } 10655 10656 /*@C 10657 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10658 10659 Collective; No Fortran Support 10660 10661 Input Parameter: 10662 . mat - the matrix 10663 10664 Output Parameter: 10665 . values - the block inverses in column major order (FORTRAN-like) 10666 10667 Level: advanced 10668 10669 Notes: 10670 The size of the blocks is determined by the block size of the matrix. 10671 10672 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10673 10674 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10675 10676 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10677 @*/ 10678 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10679 { 10680 PetscFunctionBegin; 10681 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10682 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10683 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10684 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10685 PetscFunctionReturn(PETSC_SUCCESS); 10686 } 10687 10688 /*@ 10689 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10690 10691 Collective; No Fortran Support 10692 10693 Input Parameters: 10694 + mat - the matrix 10695 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10696 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10697 10698 Output Parameter: 10699 . values - the block inverses in column major order (FORTRAN-like) 10700 10701 Level: advanced 10702 10703 Notes: 10704 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10705 10706 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10707 10708 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10709 @*/ 10710 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10711 { 10712 PetscFunctionBegin; 10713 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10714 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10715 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10716 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10717 PetscFunctionReturn(PETSC_SUCCESS); 10718 } 10719 10720 /*@ 10721 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10722 10723 Collective 10724 10725 Input Parameters: 10726 + A - the matrix 10727 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10728 10729 Level: advanced 10730 10731 Note: 10732 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10733 10734 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10735 @*/ 10736 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10737 { 10738 const PetscScalar *vals; 10739 PetscInt *dnnz; 10740 PetscInt m, rstart, rend, bs, i, j; 10741 10742 PetscFunctionBegin; 10743 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10744 PetscCall(MatGetBlockSize(A, &bs)); 10745 PetscCall(MatGetLocalSize(A, &m, NULL)); 10746 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10747 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10748 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10749 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10750 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10751 PetscCall(PetscFree(dnnz)); 10752 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10753 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10754 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10755 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10756 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10757 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10758 PetscFunctionReturn(PETSC_SUCCESS); 10759 } 10760 10761 /*@ 10762 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10763 via `MatTransposeColoringCreate()`. 10764 10765 Collective 10766 10767 Input Parameter: 10768 . c - coloring context 10769 10770 Level: intermediate 10771 10772 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10773 @*/ 10774 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10775 { 10776 MatTransposeColoring matcolor = *c; 10777 10778 PetscFunctionBegin; 10779 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10780 if (--((PetscObject)matcolor)->refct > 0) { 10781 matcolor = NULL; 10782 PetscFunctionReturn(PETSC_SUCCESS); 10783 } 10784 10785 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10786 PetscCall(PetscFree(matcolor->rows)); 10787 PetscCall(PetscFree(matcolor->den2sp)); 10788 PetscCall(PetscFree(matcolor->colorforcol)); 10789 PetscCall(PetscFree(matcolor->columns)); 10790 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10791 PetscCall(PetscHeaderDestroy(c)); 10792 PetscFunctionReturn(PETSC_SUCCESS); 10793 } 10794 10795 /*@ 10796 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10797 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10798 `MatTransposeColoring` to sparse `B`. 10799 10800 Collective 10801 10802 Input Parameters: 10803 + coloring - coloring context created with `MatTransposeColoringCreate()` 10804 - B - sparse matrix 10805 10806 Output Parameter: 10807 . Btdense - dense matrix $B^T$ 10808 10809 Level: developer 10810 10811 Note: 10812 These are used internally for some implementations of `MatRARt()` 10813 10814 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10815 @*/ 10816 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10817 { 10818 PetscFunctionBegin; 10819 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10820 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10821 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10822 10823 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10824 PetscFunctionReturn(PETSC_SUCCESS); 10825 } 10826 10827 /*@ 10828 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10829 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10830 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10831 $C_{sp}$ from $C_{den}$. 10832 10833 Collective 10834 10835 Input Parameters: 10836 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10837 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10838 10839 Output Parameter: 10840 . Csp - sparse matrix 10841 10842 Level: developer 10843 10844 Note: 10845 These are used internally for some implementations of `MatRARt()` 10846 10847 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10848 @*/ 10849 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10850 { 10851 PetscFunctionBegin; 10852 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10853 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10854 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10855 10856 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10857 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10858 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10859 PetscFunctionReturn(PETSC_SUCCESS); 10860 } 10861 10862 /*@ 10863 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10864 10865 Collective 10866 10867 Input Parameters: 10868 + mat - the matrix product C 10869 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10870 10871 Output Parameter: 10872 . color - the new coloring context 10873 10874 Level: intermediate 10875 10876 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10877 `MatTransColoringApplyDenToSp()` 10878 @*/ 10879 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10880 { 10881 MatTransposeColoring c; 10882 MPI_Comm comm; 10883 10884 PetscFunctionBegin; 10885 PetscAssertPointer(color, 3); 10886 10887 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10888 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10889 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10890 c->ctype = iscoloring->ctype; 10891 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10892 *color = c; 10893 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10894 PetscFunctionReturn(PETSC_SUCCESS); 10895 } 10896 10897 /*@ 10898 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10899 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10900 10901 Not Collective 10902 10903 Input Parameter: 10904 . mat - the matrix 10905 10906 Output Parameter: 10907 . state - the current state 10908 10909 Level: intermediate 10910 10911 Notes: 10912 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10913 different matrices 10914 10915 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10916 10917 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10918 10919 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10920 @*/ 10921 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10922 { 10923 PetscFunctionBegin; 10924 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10925 *state = mat->nonzerostate; 10926 PetscFunctionReturn(PETSC_SUCCESS); 10927 } 10928 10929 /*@ 10930 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 10931 matrices from each processor 10932 10933 Collective 10934 10935 Input Parameters: 10936 + comm - the communicators the parallel matrix will live on 10937 . seqmat - the input sequential matrices 10938 . n - number of local columns (or `PETSC_DECIDE`) 10939 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10940 10941 Output Parameter: 10942 . mpimat - the parallel matrix generated 10943 10944 Level: developer 10945 10946 Note: 10947 The number of columns of the matrix in EACH processor MUST be the same. 10948 10949 .seealso: [](ch_matrices), `Mat` 10950 @*/ 10951 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 10952 { 10953 PetscMPIInt size; 10954 10955 PetscFunctionBegin; 10956 PetscCallMPI(MPI_Comm_size(comm, &size)); 10957 if (size == 1) { 10958 if (reuse == MAT_INITIAL_MATRIX) { 10959 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 10960 } else { 10961 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 10962 } 10963 PetscFunctionReturn(PETSC_SUCCESS); 10964 } 10965 10966 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"); 10967 10968 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 10969 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 10970 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 10971 PetscFunctionReturn(PETSC_SUCCESS); 10972 } 10973 10974 /*@ 10975 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 10976 10977 Collective 10978 10979 Input Parameters: 10980 + A - the matrix to create subdomains from 10981 - N - requested number of subdomains 10982 10983 Output Parameters: 10984 + n - number of subdomains resulting on this MPI process 10985 - iss - `IS` list with indices of subdomains on this MPI process 10986 10987 Level: advanced 10988 10989 Note: 10990 The number of subdomains must be smaller than the communicator size 10991 10992 .seealso: [](ch_matrices), `Mat`, `IS` 10993 @*/ 10994 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 10995 { 10996 MPI_Comm comm, subcomm; 10997 PetscMPIInt size, rank, color; 10998 PetscInt rstart, rend, k; 10999 11000 PetscFunctionBegin; 11001 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11002 PetscCallMPI(MPI_Comm_size(comm, &size)); 11003 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11004 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); 11005 *n = 1; 11006 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11007 color = rank / k; 11008 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11009 PetscCall(PetscMalloc1(1, iss)); 11010 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11011 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11012 PetscCallMPI(MPI_Comm_free(&subcomm)); 11013 PetscFunctionReturn(PETSC_SUCCESS); 11014 } 11015 11016 /*@ 11017 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11018 11019 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11020 If they are not the same, uses `MatMatMatMult()`. 11021 11022 Once the coarse grid problem is constructed, correct for interpolation operators 11023 that are not of full rank, which can legitimately happen in the case of non-nested 11024 geometric multigrid. 11025 11026 Input Parameters: 11027 + restrct - restriction operator 11028 . dA - fine grid matrix 11029 . interpolate - interpolation operator 11030 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11031 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11032 11033 Output Parameter: 11034 . A - the Galerkin coarse matrix 11035 11036 Options Database Key: 11037 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11038 11039 Level: developer 11040 11041 Note: 11042 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11043 11044 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11045 @*/ 11046 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11047 { 11048 IS zerorows; 11049 Vec diag; 11050 11051 PetscFunctionBegin; 11052 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11053 /* Construct the coarse grid matrix */ 11054 if (interpolate == restrct) { 11055 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11056 } else { 11057 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11058 } 11059 11060 /* If the interpolation matrix is not of full rank, A will have zero rows. 11061 This can legitimately happen in the case of non-nested geometric multigrid. 11062 In that event, we set the rows of the matrix to the rows of the identity, 11063 ignoring the equations (as the RHS will also be zero). */ 11064 11065 PetscCall(MatFindZeroRows(*A, &zerorows)); 11066 11067 if (zerorows != NULL) { /* if there are any zero rows */ 11068 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11069 PetscCall(MatGetDiagonal(*A, diag)); 11070 PetscCall(VecISSet(diag, zerorows, 1.0)); 11071 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11072 PetscCall(VecDestroy(&diag)); 11073 PetscCall(ISDestroy(&zerorows)); 11074 } 11075 PetscFunctionReturn(PETSC_SUCCESS); 11076 } 11077 11078 /*@C 11079 MatSetOperation - Allows user to set a matrix operation for any matrix type 11080 11081 Logically Collective 11082 11083 Input Parameters: 11084 + mat - the matrix 11085 . op - the name of the operation 11086 - f - the function that provides the operation 11087 11088 Level: developer 11089 11090 Example Usage: 11091 .vb 11092 extern PetscErrorCode usermult(Mat, Vec, Vec); 11093 11094 PetscCall(MatCreateXXX(comm, ..., &A)); 11095 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult)); 11096 .ve 11097 11098 Notes: 11099 See the file `include/petscmat.h` for a complete list of matrix 11100 operations, which all have the form MATOP_<OPERATION>, where 11101 <OPERATION> is the name (in all capital letters) of the 11102 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11103 11104 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11105 sequence as the usual matrix interface routines, since they 11106 are intended to be accessed via the usual matrix interface 11107 routines, e.g., 11108 .vb 11109 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11110 .ve 11111 11112 In particular each function MUST return `PETSC_SUCCESS` on success and 11113 nonzero on failure. 11114 11115 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11116 11117 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11118 @*/ 11119 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) 11120 { 11121 PetscFunctionBegin; 11122 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11123 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view; 11124 (((void (**)(void))mat->ops)[op]) = f; 11125 PetscFunctionReturn(PETSC_SUCCESS); 11126 } 11127 11128 /*@C 11129 MatGetOperation - Gets a matrix operation for any matrix type. 11130 11131 Not Collective 11132 11133 Input Parameters: 11134 + mat - the matrix 11135 - op - the name of the operation 11136 11137 Output Parameter: 11138 . f - the function that provides the operation 11139 11140 Level: developer 11141 11142 Example Usage: 11143 .vb 11144 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11145 11146 MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult); 11147 .ve 11148 11149 Notes: 11150 See the file include/petscmat.h for a complete list of matrix 11151 operations, which all have the form MATOP_<OPERATION>, where 11152 <OPERATION> is the name (in all capital letters) of the 11153 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11154 11155 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11156 11157 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11158 @*/ 11159 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) 11160 { 11161 PetscFunctionBegin; 11162 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11163 *f = (((void (**)(void))mat->ops)[op]); 11164 PetscFunctionReturn(PETSC_SUCCESS); 11165 } 11166 11167 /*@ 11168 MatHasOperation - Determines whether the given matrix supports the particular operation. 11169 11170 Not Collective 11171 11172 Input Parameters: 11173 + mat - the matrix 11174 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11175 11176 Output Parameter: 11177 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11178 11179 Level: advanced 11180 11181 Note: 11182 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11183 11184 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11185 @*/ 11186 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11187 { 11188 PetscFunctionBegin; 11189 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11190 PetscAssertPointer(has, 3); 11191 if (mat->ops->hasoperation) { 11192 PetscUseTypeMethod(mat, hasoperation, op, has); 11193 } else { 11194 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11195 else { 11196 *has = PETSC_FALSE; 11197 if (op == MATOP_CREATE_SUBMATRIX) { 11198 PetscMPIInt size; 11199 11200 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11201 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11202 } 11203 } 11204 } 11205 PetscFunctionReturn(PETSC_SUCCESS); 11206 } 11207 11208 /*@ 11209 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11210 11211 Collective 11212 11213 Input Parameter: 11214 . mat - the matrix 11215 11216 Output Parameter: 11217 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11218 11219 Level: beginner 11220 11221 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11222 @*/ 11223 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11224 { 11225 PetscFunctionBegin; 11226 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11227 PetscValidType(mat, 1); 11228 PetscAssertPointer(cong, 2); 11229 if (!mat->rmap || !mat->cmap) { 11230 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11231 PetscFunctionReturn(PETSC_SUCCESS); 11232 } 11233 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11234 PetscCall(PetscLayoutSetUp(mat->rmap)); 11235 PetscCall(PetscLayoutSetUp(mat->cmap)); 11236 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11237 if (*cong) mat->congruentlayouts = 1; 11238 else mat->congruentlayouts = 0; 11239 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11240 PetscFunctionReturn(PETSC_SUCCESS); 11241 } 11242 11243 PetscErrorCode MatSetInf(Mat A) 11244 { 11245 PetscFunctionBegin; 11246 PetscUseTypeMethod(A, setinf); 11247 PetscFunctionReturn(PETSC_SUCCESS); 11248 } 11249 11250 /*@ 11251 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 11252 and possibly removes small values from the graph structure. 11253 11254 Collective 11255 11256 Input Parameters: 11257 + A - the matrix 11258 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11259 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11260 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11261 . num_idx - size of 'index' array 11262 - index - array of block indices to use for graph strength of connection weight 11263 11264 Output Parameter: 11265 . graph - the resulting graph 11266 11267 Level: advanced 11268 11269 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11270 @*/ 11271 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11272 { 11273 PetscFunctionBegin; 11274 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11275 PetscValidType(A, 1); 11276 PetscValidLogicalCollectiveBool(A, scale, 3); 11277 PetscAssertPointer(graph, 7); 11278 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11279 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11280 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11281 PetscFunctionReturn(PETSC_SUCCESS); 11282 } 11283 11284 /*@ 11285 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11286 meaning the same memory is used for the matrix, and no new memory is allocated. 11287 11288 Collective 11289 11290 Input Parameters: 11291 + A - the matrix 11292 - 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 11293 11294 Level: intermediate 11295 11296 Developer Note: 11297 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11298 of the arrays in the data structure are unneeded. 11299 11300 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11301 @*/ 11302 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11303 { 11304 PetscFunctionBegin; 11305 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11306 PetscUseTypeMethod(A, eliminatezeros, keep); 11307 PetscFunctionReturn(PETSC_SUCCESS); 11308 } 11309