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 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 509 /*@C 510 MatGetRow - Gets a row of a matrix. You MUST call `MatRestoreRow()` 511 for each row that you get to ensure that your application does 512 not bleed memory. 513 514 Not Collective 515 516 Input Parameters: 517 + mat - the matrix 518 - row - the row to get 519 520 Output Parameters: 521 + ncols - if not `NULL`, the number of nonzeros in `row` 522 . cols - if not `NULL`, the column numbers 523 - vals - if not `NULL`, the numerical values 524 525 Level: advanced 526 527 Notes: 528 This routine is provided for people who need to have direct access 529 to the structure of a matrix. We hope that we provide enough 530 high-level matrix routines that few users will need it. 531 532 `MatGetRow()` always returns 0-based column indices, regardless of 533 whether the internal representation is 0-based (default) or 1-based. 534 535 For better efficiency, set `cols` and/or `vals` to `NULL` if you do 536 not wish to extract these quantities. 537 538 The user can only examine the values extracted with `MatGetRow()`; 539 the values CANNOT be altered. To change the matrix entries, one 540 must use `MatSetValues()`. 541 542 You can only have one call to `MatGetRow()` outstanding for a particular 543 matrix at a time, per processor. `MatGetRow()` can only obtain rows 544 associated with the given processor, it cannot get rows from the 545 other processors; for that we suggest using `MatCreateSubMatrices()`, then 546 `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()` 547 is in the global number of rows. 548 549 Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix. 550 551 Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly. 552 553 Fortran Note: 554 .vb 555 PetscInt, pointer :: cols(:) 556 PetscScalar, pointer :: vals(:) 557 .ve 558 559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()` 560 @*/ 561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 562 { 563 PetscInt incols; 564 565 PetscFunctionBegin; 566 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 567 PetscValidType(mat, 1); 568 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 569 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 570 MatCheckPreallocated(mat, 1); 571 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); 572 PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0)); 573 PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals); 574 if (ncols) *ncols = incols; 575 PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0)); 576 PetscFunctionReturn(PETSC_SUCCESS); 577 } 578 579 /*@ 580 MatConjugate - replaces the matrix values with their complex conjugates 581 582 Logically Collective 583 584 Input Parameter: 585 . mat - the matrix 586 587 Level: advanced 588 589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()` 590 @*/ 591 PetscErrorCode MatConjugate(Mat mat) 592 { 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 595 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 596 if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) { 597 PetscUseTypeMethod(mat, conjugate); 598 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 599 } 600 PetscFunctionReturn(PETSC_SUCCESS); 601 } 602 603 /*@C 604 MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`. 605 606 Not Collective 607 608 Input Parameters: 609 + mat - the matrix 610 . row - the row to get 611 . ncols - the number of nonzeros 612 . cols - the columns of the nonzeros 613 - vals - if nonzero the column values 614 615 Level: advanced 616 617 Notes: 618 This routine should be called after you have finished examining the entries. 619 620 This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental 621 us of the array after it has been restored. If you pass `NULL`, it will 622 not zero the pointers. Use of `cols` or `vals` after `MatRestoreRow()` is invalid. 623 624 Fortran Note: 625 .vb 626 PetscInt, pointer :: cols(:) 627 PetscScalar, pointer :: vals(:) 628 .ve 629 630 .seealso: [](ch_matrices), `Mat`, `MatGetRow()` 631 @*/ 632 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) 633 { 634 PetscFunctionBegin; 635 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 636 if (ncols) PetscAssertPointer(ncols, 3); 637 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 638 PetscTryTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals); 639 if (ncols) *ncols = 0; 640 if (cols) *cols = NULL; 641 if (vals) *vals = NULL; 642 PetscFunctionReturn(PETSC_SUCCESS); 643 } 644 645 /*@ 646 MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 647 You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag. 648 649 Not Collective 650 651 Input Parameter: 652 . mat - the matrix 653 654 Level: advanced 655 656 Note: 657 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. 658 659 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()` 660 @*/ 661 PetscErrorCode MatGetRowUpperTriangular(Mat mat) 662 { 663 PetscFunctionBegin; 664 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 665 PetscValidType(mat, 1); 666 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 667 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 668 MatCheckPreallocated(mat, 1); 669 PetscTryTypeMethod(mat, getrowuppertriangular); 670 PetscFunctionReturn(PETSC_SUCCESS); 671 } 672 673 /*@ 674 MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format. 675 676 Not Collective 677 678 Input Parameter: 679 . mat - the matrix 680 681 Level: advanced 682 683 Note: 684 This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`. 685 686 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()` 687 @*/ 688 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) 689 { 690 PetscFunctionBegin; 691 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 692 PetscValidType(mat, 1); 693 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 694 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 695 MatCheckPreallocated(mat, 1); 696 PetscTryTypeMethod(mat, restorerowuppertriangular); 697 PetscFunctionReturn(PETSC_SUCCESS); 698 } 699 700 /*@ 701 MatSetOptionsPrefix - Sets the prefix used for searching for all 702 `Mat` options in the database. 703 704 Logically Collective 705 706 Input Parameters: 707 + A - the matrix 708 - prefix - the prefix to prepend to all option names 709 710 Level: advanced 711 712 Notes: 713 A hyphen (-) must NOT be given at the beginning of the prefix name. 714 The first character of all runtime options is AUTOMATICALLY the hyphen. 715 716 This is NOT used for options for the factorization of the matrix. Normally the 717 prefix is automatically passed in from the PC calling the factorization. To set 718 it directly use `MatSetOptionsPrefixFactor()` 719 720 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()` 721 @*/ 722 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) 723 { 724 PetscFunctionBegin; 725 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 726 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix)); 727 PetscTryMethod(A, "MatSetOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 728 PetscFunctionReturn(PETSC_SUCCESS); 729 } 730 731 /*@ 732 MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for 733 for matrices created with `MatGetFactor()` 734 735 Logically Collective 736 737 Input Parameters: 738 + A - the matrix 739 - prefix - the prefix to prepend to all option names for the factored matrix 740 741 Level: developer 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 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 748 it directly when not using `KSP`/`PC` use `MatSetOptionsPrefixFactor()` 749 750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()` 751 @*/ 752 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) 753 { 754 PetscFunctionBegin; 755 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 756 if (prefix) { 757 PetscAssertPointer(prefix, 2); 758 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 759 if (prefix != A->factorprefix) { 760 PetscCall(PetscFree(A->factorprefix)); 761 PetscCall(PetscStrallocpy(prefix, &A->factorprefix)); 762 } 763 } else PetscCall(PetscFree(A->factorprefix)); 764 PetscFunctionReturn(PETSC_SUCCESS); 765 } 766 767 /*@ 768 MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for 769 for matrices created with `MatGetFactor()` 770 771 Logically Collective 772 773 Input Parameters: 774 + A - the matrix 775 - prefix - the prefix to prepend to all option names for the factored matrix 776 777 Level: developer 778 779 Notes: 780 A hyphen (-) must NOT be given at the beginning of the prefix name. 781 The first character of all runtime options is AUTOMATICALLY the hyphen. 782 783 Normally the prefix is automatically passed in from the `PC` calling the factorization. To set 784 it directly when not using `KSP`/`PC` use `MatAppendOptionsPrefixFactor()` 785 786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`, 787 `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`, 788 `MatSetOptionsPrefix()` 789 @*/ 790 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) 791 { 792 size_t len1, len2, new_len; 793 794 PetscFunctionBegin; 795 PetscValidHeader(A, 1); 796 if (!prefix) PetscFunctionReturn(PETSC_SUCCESS); 797 if (!A->factorprefix) { 798 PetscCall(MatSetOptionsPrefixFactor(A, prefix)); 799 PetscFunctionReturn(PETSC_SUCCESS); 800 } 801 PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); 802 803 PetscCall(PetscStrlen(A->factorprefix, &len1)); 804 PetscCall(PetscStrlen(prefix, &len2)); 805 new_len = len1 + len2 + 1; 806 PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix)); 807 PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1)); 808 PetscFunctionReturn(PETSC_SUCCESS); 809 } 810 811 /*@ 812 MatAppendOptionsPrefix - Appends to the prefix used for searching for all 813 matrix options in the database. 814 815 Logically Collective 816 817 Input Parameters: 818 + A - the matrix 819 - prefix - the prefix to prepend to all option names 820 821 Level: advanced 822 823 Note: 824 A hyphen (-) must NOT be given at the beginning of the prefix name. 825 The first character of all runtime options is AUTOMATICALLY the hyphen. 826 827 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()` 828 @*/ 829 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) 830 { 831 PetscFunctionBegin; 832 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 833 PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix)); 834 PetscTryMethod(A, "MatAppendOptionsPrefix_C", (Mat, const char[]), (A, prefix)); 835 PetscFunctionReturn(PETSC_SUCCESS); 836 } 837 838 /*@ 839 MatGetOptionsPrefix - Gets the prefix used for searching for all 840 matrix options in the database. 841 842 Not Collective 843 844 Input Parameter: 845 . A - the matrix 846 847 Output Parameter: 848 . prefix - pointer to the prefix string used 849 850 Level: advanced 851 852 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()` 853 @*/ 854 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) 855 { 856 PetscFunctionBegin; 857 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 858 PetscAssertPointer(prefix, 2); 859 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix)); 860 PetscFunctionReturn(PETSC_SUCCESS); 861 } 862 863 /*@ 864 MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()` 865 866 Not Collective 867 868 Input Parameter: 869 . A - the matrix 870 871 Output Parameter: 872 . state - the object state 873 874 Level: advanced 875 876 Note: 877 Object state is an integer which gets increased every time 878 the object is changed. By saving and later querying the object state 879 one can determine whether information about the object is still current. 880 881 See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed. 882 883 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()` 884 @*/ 885 PetscErrorCode MatGetState(Mat A, PetscObjectState *state) 886 { 887 PetscFunctionBegin; 888 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 889 PetscAssertPointer(state, 2); 890 PetscCall(PetscObjectStateGet((PetscObject)A, state)); 891 PetscFunctionReturn(PETSC_SUCCESS); 892 } 893 894 /*@ 895 MatResetPreallocation - Reset matrix to use the original preallocation values provided by the user, for example with `MatXAIJSetPreallocation()` 896 897 Collective 898 899 Input Parameter: 900 . A - the matrix 901 902 Level: beginner 903 904 Notes: 905 After calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY` the matrix data structures represent the nonzeros assigned to the 906 matrix. If that space is less than the preallocated space that extra preallocated space is no longer available to take on new values. `MatResetPreallocation()` 907 makes all of the preallocation space available 908 909 Current values in the matrix are lost in this call 910 911 Currently only supported for `MATAIJ` matrices. 912 913 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()` 914 @*/ 915 PetscErrorCode MatResetPreallocation(Mat A) 916 { 917 PetscFunctionBegin; 918 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 919 PetscValidType(A, 1); 920 PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A)); 921 PetscFunctionReturn(PETSC_SUCCESS); 922 } 923 924 /*@ 925 MatResetHash - Reset the matrix so that it will use a hash table for the next round of `MatSetValues()` and `MatAssemblyBegin()`/`MatAssemblyEnd()`. 926 927 Collective 928 929 Input Parameter: 930 . A - the matrix 931 932 Level: intermediate 933 934 Notes: 935 The matrix will again delete the hash table data structures after following calls to `MatAssemblyBegin()`/`MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`. 936 937 Currently only supported for `MATAIJ` matrices. 938 939 .seealso: [](ch_matrices), `Mat`, `MatResetPreallocation()` 940 @*/ 941 PetscErrorCode MatResetHash(Mat A) 942 { 943 PetscFunctionBegin; 944 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 945 PetscValidType(A, 1); 946 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()"); 947 if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS); 948 PetscUseMethod(A, "MatResetHash_C", (Mat), (A)); 949 /* These flags are used to determine whether certain setups occur */ 950 A->was_assembled = PETSC_FALSE; 951 A->assembled = PETSC_FALSE; 952 /* Log that the state of this object has changed; this will help guarantee that preconditioners get re-setup */ 953 PetscCall(PetscObjectStateIncrease((PetscObject)A)); 954 PetscFunctionReturn(PETSC_SUCCESS); 955 } 956 957 /*@ 958 MatSetUp - Sets up the internal matrix data structures for later use by the matrix 959 960 Collective 961 962 Input Parameter: 963 . A - the matrix 964 965 Level: advanced 966 967 Notes: 968 If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of 969 setting values in the matrix. 970 971 This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users 972 973 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()` 974 @*/ 975 PetscErrorCode MatSetUp(Mat A) 976 { 977 PetscFunctionBegin; 978 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 979 if (!((PetscObject)A)->type_name) { 980 PetscMPIInt size; 981 982 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size)); 983 PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ)); 984 } 985 if (!A->preallocated) PetscTryTypeMethod(A, setup); 986 PetscCall(PetscLayoutSetUp(A->rmap)); 987 PetscCall(PetscLayoutSetUp(A->cmap)); 988 A->preallocated = PETSC_TRUE; 989 PetscFunctionReturn(PETSC_SUCCESS); 990 } 991 992 #if defined(PETSC_HAVE_SAWS) 993 #include <petscviewersaws.h> 994 #endif 995 996 /* 997 If threadsafety is on extraneous matrices may be printed 998 999 This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions() 1000 */ 1001 #if !defined(PETSC_HAVE_THREADSAFETY) 1002 static PetscInt insidematview = 0; 1003 #endif 1004 1005 /*@ 1006 MatViewFromOptions - View properties of the matrix based on options set in the options database 1007 1008 Collective 1009 1010 Input Parameters: 1011 + A - the matrix 1012 . obj - optional additional object that provides the options prefix to use 1013 - name - command line option 1014 1015 Options Database Key: 1016 . -mat_view [viewertype]:... - the viewer and its options 1017 1018 Level: intermediate 1019 1020 Note: 1021 .vb 1022 If no value is provided ascii:stdout is used 1023 ascii[:[filename][:[format][:append]]] defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab, 1024 for example ascii::ascii_info prints just the information about the object not all details 1025 unless :append is given filename opens in write mode, overwriting what was already there 1026 binary[:[filename][:[format][:append]]] defaults to the file binaryoutput 1027 draw[:drawtype[:filename]] for example, draw:tikz, draw:tikz:figure.tex or draw:x 1028 socket[:port] defaults to the standard output port 1029 saws[:communicatorname] publishes object to the Scientific Application Webserver (SAWs) 1030 .ve 1031 1032 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()` 1033 @*/ 1034 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) 1035 { 1036 PetscFunctionBegin; 1037 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 1038 #if !defined(PETSC_HAVE_THREADSAFETY) 1039 if (insidematview) PetscFunctionReturn(PETSC_SUCCESS); 1040 #endif 1041 PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name)); 1042 PetscFunctionReturn(PETSC_SUCCESS); 1043 } 1044 1045 /*@ 1046 MatView - display information about a matrix in a variety ways 1047 1048 Collective on viewer 1049 1050 Input Parameters: 1051 + mat - the matrix 1052 - viewer - visualization context 1053 1054 Options Database Keys: 1055 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 1056 . -mat_view ::ascii_info_detail - Prints more detailed info 1057 . -mat_view - Prints matrix in ASCII format 1058 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 1059 . -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 1060 . -display <name> - Sets display name (default is host) 1061 . -draw_pause <sec> - Sets number of seconds to pause after display 1062 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details) 1063 . -viewer_socket_machine <machine> - - 1064 . -viewer_socket_port <port> - - 1065 . -mat_view binary - save matrix to file in binary format 1066 - -viewer_binary_filename <name> - - 1067 1068 Level: beginner 1069 1070 Notes: 1071 The available visualization contexts include 1072 + `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices 1073 . `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD` 1074 . `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm 1075 - `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure 1076 1077 The user can open alternative visualization contexts with 1078 + `PetscViewerASCIIOpen()` - Outputs matrix to a specified file 1079 . `PetscViewerBinaryOpen()` - Outputs matrix in binary to a specified file; corresponding input uses `MatLoad()` 1080 . `PetscViewerDrawOpen()` - Outputs nonzero matrix nonzero structure to an X window display 1081 - `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer. 1082 1083 The user can call `PetscViewerPushFormat()` to specify the output 1084 format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`, 1085 `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`). Available formats include 1086 + `PETSC_VIEWER_DEFAULT` - default, prints matrix contents 1087 . `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format 1088 . `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros 1089 . `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse format common among all matrix types 1090 . `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default) 1091 . `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix size and structure (not the matrix entries) 1092 - `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries) 1093 1094 The ASCII viewers are only recommended for small matrices on at most a moderate number of processes, 1095 the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format. 1096 1097 In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer). 1098 1099 See the manual page for `MatLoad()` for the exact format of the binary file when the binary 1100 viewer is used. 1101 1102 See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary 1103 viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python. 1104 1105 One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure, 1106 and then use the following mouse functions. 1107 .vb 1108 left mouse: zoom in 1109 middle mouse: zoom out 1110 right mouse: continue with the simulation 1111 .ve 1112 1113 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, 1114 `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()` 1115 @*/ 1116 PetscErrorCode MatView(Mat mat, PetscViewer viewer) 1117 { 1118 PetscInt rows, cols, rbs, cbs; 1119 PetscBool isascii, isstring, issaws; 1120 PetscViewerFormat format; 1121 PetscMPIInt size; 1122 1123 PetscFunctionBegin; 1124 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1125 PetscValidType(mat, 1); 1126 if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer)); 1127 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1128 1129 PetscCall(PetscViewerGetFormat(viewer, &format)); 1130 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size)); 1131 if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS); 1132 1133 #if !defined(PETSC_HAVE_THREADSAFETY) 1134 insidematview++; 1135 #endif 1136 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring)); 1137 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 1138 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws)); 1139 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"); 1140 1141 PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0)); 1142 if (isascii) { 1143 if (!mat->preallocated) { 1144 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n")); 1145 #if !defined(PETSC_HAVE_THREADSAFETY) 1146 insidematview--; 1147 #endif 1148 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1149 PetscFunctionReturn(PETSC_SUCCESS); 1150 } 1151 if (!mat->assembled) { 1152 PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n")); 1153 #if !defined(PETSC_HAVE_THREADSAFETY) 1154 insidematview--; 1155 #endif 1156 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1157 PetscFunctionReturn(PETSC_SUCCESS); 1158 } 1159 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer)); 1160 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1161 MatNullSpace nullsp, transnullsp; 1162 1163 PetscCall(PetscViewerASCIIPushTab(viewer)); 1164 PetscCall(MatGetSize(mat, &rows, &cols)); 1165 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 1166 if (rbs != 1 || cbs != 1) { 1167 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" : "")); 1168 else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : "")); 1169 } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols)); 1170 if (mat->factortype) { 1171 MatSolverType solver; 1172 PetscCall(MatFactorGetSolverType(mat, &solver)); 1173 PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver)); 1174 } 1175 if (mat->ops->getinfo) { 1176 PetscBool is_constant_or_diagonal; 1177 1178 // Don't print nonzero information for constant or diagonal matrices, it just adds noise to the output 1179 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &is_constant_or_diagonal, MATCONSTANTDIAGONAL, MATDIAGONAL, "")); 1180 if (!is_constant_or_diagonal) { 1181 MatInfo info; 1182 1183 PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info)); 1184 PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated)); 1185 if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs)); 1186 } 1187 } 1188 PetscCall(MatGetNullSpace(mat, &nullsp)); 1189 PetscCall(MatGetTransposeNullSpace(mat, &transnullsp)); 1190 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached null space\n")); 1191 if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached transposed null space\n")); 1192 PetscCall(MatGetNearNullSpace(mat, &nullsp)); 1193 if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, " has attached near null space\n")); 1194 PetscCall(PetscViewerASCIIPushTab(viewer)); 1195 PetscCall(MatProductView(mat, viewer)); 1196 PetscCall(PetscViewerASCIIPopTab(viewer)); 1197 if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 1198 IS tmp; 1199 1200 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp)); 1201 PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes")); 1202 PetscCall(PetscViewerASCIIPushTab(viewer)); 1203 PetscCall(ISView(tmp, viewer)); 1204 PetscCall(PetscViewerASCIIPopTab(viewer)); 1205 PetscCall(ISDestroy(&tmp)); 1206 } 1207 } 1208 } else if (issaws) { 1209 #if defined(PETSC_HAVE_SAWS) 1210 PetscMPIInt rank; 1211 1212 PetscCall(PetscObjectName((PetscObject)mat)); 1213 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 1214 if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer)); 1215 #endif 1216 } else if (isstring) { 1217 const char *type; 1218 PetscCall(MatGetType(mat, &type)); 1219 PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type)); 1220 PetscTryTypeMethod(mat, view, viewer); 1221 } 1222 if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) { 1223 PetscCall(PetscViewerASCIIPushTab(viewer)); 1224 PetscUseTypeMethod(mat, viewnative, viewer); 1225 PetscCall(PetscViewerASCIIPopTab(viewer)); 1226 } else if (mat->ops->view) { 1227 PetscCall(PetscViewerASCIIPushTab(viewer)); 1228 PetscUseTypeMethod(mat, view, viewer); 1229 PetscCall(PetscViewerASCIIPopTab(viewer)); 1230 } 1231 if (isascii) { 1232 PetscCall(PetscViewerGetFormat(viewer, &format)); 1233 if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer)); 1234 } 1235 PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0)); 1236 #if !defined(PETSC_HAVE_THREADSAFETY) 1237 insidematview--; 1238 #endif 1239 PetscFunctionReturn(PETSC_SUCCESS); 1240 } 1241 1242 #if defined(PETSC_USE_DEBUG) 1243 #include <../src/sys/totalview/tv_data_display.h> 1244 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) 1245 { 1246 TV_add_row("Local rows", "int", &mat->rmap->n); 1247 TV_add_row("Local columns", "int", &mat->cmap->n); 1248 TV_add_row("Global rows", "int", &mat->rmap->N); 1249 TV_add_row("Global columns", "int", &mat->cmap->N); 1250 TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name); 1251 return TV_format_OK; 1252 } 1253 #endif 1254 1255 /*@ 1256 MatLoad - Loads a matrix that has been stored in binary/HDF5 format 1257 with `MatView()`. The matrix format is determined from the options database. 1258 Generates a parallel MPI matrix if the communicator has more than one 1259 processor. The default matrix type is `MATAIJ`. 1260 1261 Collective 1262 1263 Input Parameters: 1264 + mat - the newly loaded matrix, this needs to have been created with `MatCreate()` 1265 or some related function before a call to `MatLoad()` 1266 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer 1267 1268 Options Database Key: 1269 . -matload_block_size <bs> - set block size 1270 1271 Level: beginner 1272 1273 Notes: 1274 If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the 1275 `Mat` before calling this routine if you wish to set it from the options database. 1276 1277 `MatLoad()` automatically loads into the options database any options 1278 given in the file filename.info where filename is the name of the file 1279 that was passed to the `PetscViewerBinaryOpen()`. The options in the info 1280 file will be ignored if you use the -viewer_binary_skip_info option. 1281 1282 If the type or size of mat is not set before a call to `MatLoad()`, PETSc 1283 sets the default matrix type AIJ and sets the local and global sizes. 1284 If type and/or size is already set, then the same are used. 1285 1286 In parallel, each processor can load a subset of rows (or the 1287 entire matrix). This routine is especially useful when a large 1288 matrix is stored on disk and only part of it is desired on each 1289 processor. For example, a parallel solver may access only some of 1290 the rows from each processor. The algorithm used here reads 1291 relatively small blocks of data rather than reading the entire 1292 matrix and then subsetting it. 1293 1294 Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`. 1295 Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`, 1296 or the sequence like 1297 .vb 1298 `PetscViewer` v; 1299 `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v); 1300 `PetscViewerSetType`(v,`PETSCVIEWERBINARY`); 1301 `PetscViewerSetFromOptions`(v); 1302 `PetscViewerFileSetMode`(v,`FILE_MODE_READ`); 1303 `PetscViewerFileSetName`(v,"datafile"); 1304 .ve 1305 The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option 1306 .vb 1307 -viewer_type {binary, hdf5} 1308 .ve 1309 1310 See the example src/ksp/ksp/tutorials/ex27.c with the first approach, 1311 and src/mat/tutorials/ex10.c with the second approach. 1312 1313 In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks 1314 is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another. 1315 Multiple objects, both matrices and vectors, can be stored within the same file. 1316 Their `PetscObject` name is ignored; they are loaded in the order of their storage. 1317 1318 Most users should not need to know the details of the binary storage 1319 format, since `MatLoad()` and `MatView()` completely hide these details. 1320 But for anyone who is interested, the standard binary matrix storage 1321 format is 1322 1323 .vb 1324 PetscInt MAT_FILE_CLASSID 1325 PetscInt number of rows 1326 PetscInt number of columns 1327 PetscInt total number of nonzeros 1328 PetscInt *number nonzeros in each row 1329 PetscInt *column indices of all nonzeros (starting index is zero) 1330 PetscScalar *values of all nonzeros 1331 .ve 1332 If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be 1333 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 1334 case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`. 1335 1336 PETSc automatically does the byte swapping for 1337 machines that store the bytes reversed. Thus if you write your own binary 1338 read/write routines you have to swap the bytes; see `PetscBinaryRead()` 1339 and `PetscBinaryWrite()` to see how this may be done. 1340 1341 In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used. 1342 Each processor's chunk is loaded independently by its owning MPI process. 1343 Multiple objects, both matrices and vectors, can be stored within the same file. 1344 They are looked up by their PetscObject name. 1345 1346 As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use 1347 by default the same structure and naming of the AIJ arrays and column count 1348 within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g. 1349 .vb 1350 save example.mat A b -v7.3 1351 .ve 1352 can be directly read by this routine (see Reference 1 for details). 1353 1354 Depending on your MATLAB version, this format might be a default, 1355 otherwise you can set it as default in Preferences. 1356 1357 Unless -nocompression flag is used to save the file in MATLAB, 1358 PETSc must be configured with ZLIB package. 1359 1360 See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c 1361 1362 This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5` 1363 1364 Corresponding `MatView()` is not yet implemented. 1365 1366 The loaded matrix is actually a transpose of the original one in MATLAB, 1367 unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above). 1368 With this format, matrix is automatically transposed by PETSc, 1369 unless the matrix is marked as SPD or symmetric 1370 (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`). 1371 1372 See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version> 1373 1374 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()` 1375 @*/ 1376 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) 1377 { 1378 PetscBool flg; 1379 1380 PetscFunctionBegin; 1381 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1382 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 1383 1384 if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ)); 1385 1386 flg = PETSC_FALSE; 1387 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL)); 1388 if (flg) { 1389 PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE)); 1390 PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 1391 } 1392 flg = PETSC_FALSE; 1393 PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL)); 1394 if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE)); 1395 1396 PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0)); 1397 PetscUseTypeMethod(mat, load, viewer); 1398 PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0)); 1399 PetscFunctionReturn(PETSC_SUCCESS); 1400 } 1401 1402 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) 1403 { 1404 Mat_Redundant *redund = *redundant; 1405 1406 PetscFunctionBegin; 1407 if (redund) { 1408 if (redund->matseq) { /* via MatCreateSubMatrices() */ 1409 PetscCall(ISDestroy(&redund->isrow)); 1410 PetscCall(ISDestroy(&redund->iscol)); 1411 PetscCall(MatDestroySubMatrices(1, &redund->matseq)); 1412 } else { 1413 PetscCall(PetscFree2(redund->send_rank, redund->recv_rank)); 1414 PetscCall(PetscFree(redund->sbuf_j)); 1415 PetscCall(PetscFree(redund->sbuf_a)); 1416 for (PetscInt i = 0; i < redund->nrecvs; i++) { 1417 PetscCall(PetscFree(redund->rbuf_j[i])); 1418 PetscCall(PetscFree(redund->rbuf_a[i])); 1419 } 1420 PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a)); 1421 } 1422 1423 if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm)); 1424 PetscCall(PetscFree(redund)); 1425 } 1426 PetscFunctionReturn(PETSC_SUCCESS); 1427 } 1428 1429 /*@ 1430 MatDestroy - Frees space taken by a matrix. 1431 1432 Collective 1433 1434 Input Parameter: 1435 . A - the matrix 1436 1437 Level: beginner 1438 1439 Developer Note: 1440 Some special arrays of matrices are not destroyed in this routine but instead by the routines called by 1441 `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines. 1442 `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes 1443 if changes are needed here. 1444 1445 .seealso: [](ch_matrices), `Mat`, `MatCreate()` 1446 @*/ 1447 PetscErrorCode MatDestroy(Mat *A) 1448 { 1449 PetscFunctionBegin; 1450 if (!*A) PetscFunctionReturn(PETSC_SUCCESS); 1451 PetscValidHeaderSpecific(*A, MAT_CLASSID, 1); 1452 if (--((PetscObject)*A)->refct > 0) { 1453 *A = NULL; 1454 PetscFunctionReturn(PETSC_SUCCESS); 1455 } 1456 1457 /* if memory was published with SAWs then destroy it */ 1458 PetscCall(PetscObjectSAWsViewOff((PetscObject)*A)); 1459 PetscTryTypeMethod(*A, destroy); 1460 1461 PetscCall(PetscFree((*A)->factorprefix)); 1462 PetscCall(PetscFree((*A)->defaultvectype)); 1463 PetscCall(PetscFree((*A)->defaultrandtype)); 1464 PetscCall(PetscFree((*A)->bsizes)); 1465 PetscCall(PetscFree((*A)->solvertype)); 1466 for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i])); 1467 if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL; 1468 PetscCall(MatDestroy_Redundant(&(*A)->redundant)); 1469 PetscCall(MatProductClear(*A)); 1470 PetscCall(MatNullSpaceDestroy(&(*A)->nullsp)); 1471 PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp)); 1472 PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp)); 1473 PetscCall(MatDestroy(&(*A)->schur)); 1474 PetscCall(PetscLayoutDestroy(&(*A)->rmap)); 1475 PetscCall(PetscLayoutDestroy(&(*A)->cmap)); 1476 PetscCall(PetscHeaderDestroy(A)); 1477 PetscFunctionReturn(PETSC_SUCCESS); 1478 } 1479 1480 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1481 /*@ 1482 MatSetValues - Inserts or adds a block of values into a matrix. 1483 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1484 MUST be called after all calls to `MatSetValues()` have been completed. 1485 1486 Not Collective 1487 1488 Input Parameters: 1489 + mat - the matrix 1490 . m - the number of rows 1491 . idxm - the global indices of the rows 1492 . n - the number of columns 1493 . idxn - the global indices of the columns 1494 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 1495 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1496 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1497 1498 Level: beginner 1499 1500 Notes: 1501 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1502 options cannot be mixed without intervening calls to the assembly 1503 routines. 1504 1505 `MatSetValues()` uses 0-based row and column numbers in Fortran 1506 as well as in C. 1507 1508 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1509 simply ignored. This allows easily inserting element stiffness matrices 1510 with homogeneous Dirichlet boundary conditions that you don't want represented 1511 in the matrix. 1512 1513 Efficiency Alert: 1514 The routine `MatSetValuesBlocked()` may offer much better efficiency 1515 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1516 1517 Fortran Notes: 1518 If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example, 1519 .vb 1520 call MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 1521 .ve 1522 1523 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1524 1525 Developer Note: 1526 This is labeled with C so does not automatically generate Fortran stubs and interfaces 1527 because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays. 1528 1529 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1530 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1531 @*/ 1532 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 1533 { 1534 PetscFunctionBeginHot; 1535 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1536 PetscValidType(mat, 1); 1537 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1538 PetscAssertPointer(idxm, 3); 1539 PetscAssertPointer(idxn, 5); 1540 MatCheckPreallocated(mat, 1); 1541 1542 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 1543 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 1544 1545 if (PetscDefined(USE_DEBUG)) { 1546 PetscInt i, j; 1547 1548 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1549 if (v) { 1550 for (i = 0; i < m; i++) { 1551 for (j = 0; j < n; j++) { 1552 if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j])) 1553 #if defined(PETSC_USE_COMPLEX) 1554 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]); 1555 #else 1556 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]); 1557 #endif 1558 } 1559 } 1560 } 1561 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); 1562 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); 1563 } 1564 1565 if (mat->assembled) { 1566 mat->was_assembled = PETSC_TRUE; 1567 mat->assembled = PETSC_FALSE; 1568 } 1569 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1570 PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv); 1571 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1572 PetscFunctionReturn(PETSC_SUCCESS); 1573 } 1574 1575 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1576 /*@ 1577 MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns 1578 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 1579 MUST be called after all calls to `MatSetValues()` have been completed. 1580 1581 Not Collective 1582 1583 Input Parameters: 1584 + mat - the matrix 1585 . ism - the rows to provide 1586 . isn - the columns to provide 1587 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 1588 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1589 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 1590 1591 Level: beginner 1592 1593 Notes: 1594 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1595 1596 Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES` 1597 options cannot be mixed without intervening calls to the assembly 1598 routines. 1599 1600 `MatSetValues()` uses 0-based row and column numbers in Fortran 1601 as well as in C. 1602 1603 Negative indices may be passed in `ism` and `isn`, these rows and columns are 1604 simply ignored. This allows easily inserting element stiffness matrices 1605 with homogeneous Dirichlet boundary conditions that you don't want represented 1606 in the matrix. 1607 1608 Fortran Note: 1609 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1610 1611 Efficiency Alert: 1612 The routine `MatSetValuesBlocked()` may offer much better efficiency 1613 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1614 1615 This is currently not optimized for any particular `ISType` 1616 1617 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1618 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1619 @*/ 1620 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) 1621 { 1622 PetscInt m, n; 1623 const PetscInt *rows, *cols; 1624 1625 PetscFunctionBeginHot; 1626 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1627 PetscCall(ISGetIndices(ism, &rows)); 1628 PetscCall(ISGetIndices(isn, &cols)); 1629 PetscCall(ISGetLocalSize(ism, &m)); 1630 PetscCall(ISGetLocalSize(isn, &n)); 1631 PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv)); 1632 PetscCall(ISRestoreIndices(ism, &rows)); 1633 PetscCall(ISRestoreIndices(isn, &cols)); 1634 PetscFunctionReturn(PETSC_SUCCESS); 1635 } 1636 1637 /*@ 1638 MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1639 values into a matrix 1640 1641 Not Collective 1642 1643 Input Parameters: 1644 + mat - the matrix 1645 . row - the (block) row to set 1646 - v - a one-dimensional array that contains the values. For `MATBAIJ` they are implicitly stored as a two-dimensional array, by default in row-major order. 1647 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1648 1649 Level: intermediate 1650 1651 Notes: 1652 The values, `v`, are column-oriented (for the block version) and sorted 1653 1654 All the nonzero values in `row` must be provided 1655 1656 The matrix must have previously had its column indices set, likely by having been assembled. 1657 1658 `row` must belong to this MPI process 1659 1660 Fortran Note: 1661 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1662 1663 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1664 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()` 1665 @*/ 1666 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) 1667 { 1668 PetscInt globalrow; 1669 1670 PetscFunctionBegin; 1671 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1672 PetscValidType(mat, 1); 1673 PetscAssertPointer(v, 3); 1674 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow)); 1675 PetscCall(MatSetValuesRow(mat, globalrow, v)); 1676 PetscFunctionReturn(PETSC_SUCCESS); 1677 } 1678 1679 /*@ 1680 MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero 1681 values into a matrix 1682 1683 Not Collective 1684 1685 Input Parameters: 1686 + mat - the matrix 1687 . row - the (block) row to set 1688 - 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 1689 1690 Level: advanced 1691 1692 Notes: 1693 The values, `v`, are column-oriented for the block version. 1694 1695 All the nonzeros in `row` must be provided 1696 1697 THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used. 1698 1699 `row` must belong to this process 1700 1701 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 1702 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES` 1703 @*/ 1704 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) 1705 { 1706 PetscFunctionBeginHot; 1707 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1708 PetscValidType(mat, 1); 1709 MatCheckPreallocated(mat, 1); 1710 PetscAssertPointer(v, 3); 1711 PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values"); 1712 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 1713 mat->insertmode = INSERT_VALUES; 1714 1715 if (mat->assembled) { 1716 mat->was_assembled = PETSC_TRUE; 1717 mat->assembled = PETSC_FALSE; 1718 } 1719 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 1720 PetscUseTypeMethod(mat, setvaluesrow, row, v); 1721 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 1722 PetscFunctionReturn(PETSC_SUCCESS); 1723 } 1724 1725 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 1726 /*@ 1727 MatSetValuesStencil - Inserts or adds a block of values into a matrix. 1728 Using structured grid indexing 1729 1730 Not Collective 1731 1732 Input Parameters: 1733 + mat - the matrix 1734 . m - number of rows being entered 1735 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered 1736 . n - number of columns being entered 1737 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered 1738 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 1739 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1740 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values 1741 1742 Level: beginner 1743 1744 Notes: 1745 By default the values, `v`, are row-oriented. See `MatSetOption()` for other options. 1746 1747 Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1748 options cannot be mixed without intervening calls to the assembly 1749 routines. 1750 1751 The grid coordinates are across the entire grid, not just the local portion 1752 1753 `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran 1754 as well as in C. 1755 1756 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1757 1758 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1759 or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1760 1761 The columns and rows in the stencil passed in MUST be contained within the 1762 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1763 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1764 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1765 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1766 1767 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 1768 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 1769 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 1770 `DM_BOUNDARY_PERIODIC` boundary type. 1771 1772 For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have 1773 a single value per point) you can skip filling those indices. 1774 1775 Inspired by the structured grid interface to the HYPRE package 1776 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1777 1778 Fortran Note: 1779 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1780 1781 Efficiency Alert: 1782 The routine `MatSetValuesBlockedStencil()` may offer much better efficiency 1783 for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`). 1784 1785 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1786 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil` 1787 @*/ 1788 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1789 { 1790 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1791 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1792 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1793 1794 PetscFunctionBegin; 1795 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1796 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1797 PetscValidType(mat, 1); 1798 PetscAssertPointer(idxm, 3); 1799 PetscAssertPointer(idxn, 5); 1800 1801 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1802 jdxm = buf; 1803 jdxn = buf + m; 1804 } else { 1805 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1806 jdxm = bufm; 1807 jdxn = bufn; 1808 } 1809 for (i = 0; i < m; i++) { 1810 for (j = 0; j < 3 - sdim; j++) dxm++; 1811 tmp = *dxm++ - starts[0]; 1812 for (j = 0; j < dim - 1; j++) { 1813 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1814 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1815 } 1816 if (mat->stencil.noc) dxm++; 1817 jdxm[i] = tmp; 1818 } 1819 for (i = 0; i < n; i++) { 1820 for (j = 0; j < 3 - sdim; j++) dxn++; 1821 tmp = *dxn++ - starts[0]; 1822 for (j = 0; j < dim - 1; j++) { 1823 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1824 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1825 } 1826 if (mat->stencil.noc) dxn++; 1827 jdxn[i] = tmp; 1828 } 1829 PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv)); 1830 PetscCall(PetscFree2(bufm, bufn)); 1831 PetscFunctionReturn(PETSC_SUCCESS); 1832 } 1833 1834 /*@ 1835 MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix. 1836 Using structured grid indexing 1837 1838 Not Collective 1839 1840 Input Parameters: 1841 + mat - the matrix 1842 . m - number of rows being entered 1843 . idxm - grid coordinates for matrix rows being entered 1844 . n - number of columns being entered 1845 . idxn - grid coordinates for matrix columns being entered 1846 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 1847 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 1848 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values 1849 1850 Level: beginner 1851 1852 Notes: 1853 By default the values, `v`, are row-oriented and unsorted. 1854 See `MatSetOption()` for other options. 1855 1856 Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES` 1857 options cannot be mixed without intervening calls to the assembly 1858 routines. 1859 1860 The grid coordinates are across the entire grid, not just the local portion 1861 1862 `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran 1863 as well as in C. 1864 1865 For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine 1866 1867 In order to use this routine you must either obtain the matrix with `DMCreateMatrix()` 1868 or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first. 1869 1870 The columns and rows in the stencil passed in MUST be contained within the 1871 ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example, 1872 if you create a `DMDA` with an overlap of one grid level and on a particular process its first 1873 local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the 1874 first i index you can use in your column and row indices in `MatSetStencil()` is 5. 1875 1876 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 1877 simply ignored. This allows easily inserting element stiffness matrices 1878 with homogeneous Dirichlet boundary conditions that you don't want represented 1879 in the matrix. 1880 1881 Inspired by the structured grid interface to the HYPRE package 1882 (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods) 1883 1884 Fortran Notes: 1885 `idxm` and `idxn` should be declared as 1886 .vb 1887 MatStencil idxm(4,m),idxn(4,n) 1888 .ve 1889 and the values inserted using 1890 .vb 1891 idxm(MatStencil_i,1) = i 1892 idxm(MatStencil_j,1) = j 1893 idxm(MatStencil_k,1) = k 1894 etc 1895 .ve 1896 1897 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 1898 1899 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1900 `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`, 1901 `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` 1902 @*/ 1903 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) 1904 { 1905 PetscInt buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn; 1906 PetscInt j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp; 1907 PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc); 1908 1909 PetscFunctionBegin; 1910 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 1911 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1912 PetscValidType(mat, 1); 1913 PetscAssertPointer(idxm, 3); 1914 PetscAssertPointer(idxn, 5); 1915 PetscAssertPointer(v, 6); 1916 1917 if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 1918 jdxm = buf; 1919 jdxn = buf + m; 1920 } else { 1921 PetscCall(PetscMalloc2(m, &bufm, n, &bufn)); 1922 jdxm = bufm; 1923 jdxn = bufn; 1924 } 1925 for (i = 0; i < m; i++) { 1926 for (j = 0; j < 3 - sdim; j++) dxm++; 1927 tmp = *dxm++ - starts[0]; 1928 for (j = 0; j < sdim - 1; j++) { 1929 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1930 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 1931 } 1932 dxm++; 1933 jdxm[i] = tmp; 1934 } 1935 for (i = 0; i < n; i++) { 1936 for (j = 0; j < 3 - sdim; j++) dxn++; 1937 tmp = *dxn++ - starts[0]; 1938 for (j = 0; j < sdim - 1; j++) { 1939 if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1; 1940 else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1]; 1941 } 1942 dxn++; 1943 jdxn[i] = tmp; 1944 } 1945 PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv)); 1946 PetscCall(PetscFree2(bufm, bufn)); 1947 PetscFunctionReturn(PETSC_SUCCESS); 1948 } 1949 1950 /*@ 1951 MatSetStencil - Sets the grid information for setting values into a matrix via 1952 `MatSetValuesStencil()` 1953 1954 Not Collective 1955 1956 Input Parameters: 1957 + mat - the matrix 1958 . dim - dimension of the grid 1, 2, or 3 1959 . dims - number of grid points in x, y, and z direction, including ghost points on your processor 1960 . starts - starting point of ghost nodes on your processor in x, y, and z direction 1961 - dof - number of degrees of freedom per node 1962 1963 Level: beginner 1964 1965 Notes: 1966 Inspired by the structured grid interface to the HYPRE package 1967 (www.llnl.gov/CASC/hyper) 1968 1969 For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the 1970 user. 1971 1972 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()` 1973 `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()` 1974 @*/ 1975 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) 1976 { 1977 PetscFunctionBegin; 1978 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 1979 PetscAssertPointer(dims, 3); 1980 PetscAssertPointer(starts, 4); 1981 1982 mat->stencil.dim = dim + (dof > 1); 1983 for (PetscInt i = 0; i < dim; i++) { 1984 mat->stencil.dims[i] = dims[dim - i - 1]; /* copy the values in backwards */ 1985 mat->stencil.starts[i] = starts[dim - i - 1]; 1986 } 1987 mat->stencil.dims[dim] = dof; 1988 mat->stencil.starts[dim] = 0; 1989 mat->stencil.noc = (PetscBool)(dof == 1); 1990 PetscFunctionReturn(PETSC_SUCCESS); 1991 } 1992 1993 /*@ 1994 MatSetValuesBlocked - Inserts or adds a block of values into a matrix. 1995 1996 Not Collective 1997 1998 Input Parameters: 1999 + mat - the matrix 2000 . m - the number of block rows 2001 . idxm - the global block indices 2002 . n - the number of block columns 2003 . idxn - the global block indices 2004 . v - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 2005 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2006 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values 2007 2008 Level: intermediate 2009 2010 Notes: 2011 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call 2012 MatXXXXSetPreallocation() or `MatSetUp()` before using this routine. 2013 2014 The `m` and `n` count the NUMBER of blocks in the row direction and column direction, 2015 NOT the total number of rows/columns; for example, if the block size is 2 and 2016 you are passing in values for rows 2,3,4,5 then `m` would be 2 (not 4). 2017 The values in `idxm` would be 1 2; that is the first index for each block divided by 2018 the block size. 2019 2020 You must call `MatSetBlockSize()` when constructing this matrix (before 2021 preallocating it). 2022 2023 By default, the values, `v`, are stored in row-major order. See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2024 2025 Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES` 2026 options cannot be mixed without intervening calls to the assembly 2027 routines. 2028 2029 `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran 2030 as well as in C. 2031 2032 Negative indices may be passed in `idxm` and `idxn`, these rows and columns are 2033 simply ignored. This allows easily inserting element stiffness matrices 2034 with homogeneous Dirichlet boundary conditions that you don't want represented 2035 in the matrix. 2036 2037 Each time an entry is set within a sparse matrix via `MatSetValues()`, 2038 internal searching must be done to determine where to place the 2039 data in the matrix storage space. By instead inserting blocks of 2040 entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is 2041 reduced. 2042 2043 Example: 2044 .vb 2045 Suppose m=n=2 and block size(bs) = 2 The array is 2046 2047 1 2 | 3 4 2048 5 6 | 7 8 2049 - - - | - - - 2050 9 10 | 11 12 2051 13 14 | 15 16 2052 2053 v[] should be passed in like 2054 v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 2055 2056 If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then 2057 v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16] 2058 .ve 2059 2060 Fortran Notes: 2061 If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example, 2062 .vb 2063 call MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES, ierr) 2064 .ve 2065 2066 If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2067 2068 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()` 2069 @*/ 2070 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) 2071 { 2072 PetscFunctionBeginHot; 2073 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2074 PetscValidType(mat, 1); 2075 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2076 PetscAssertPointer(idxm, 3); 2077 PetscAssertPointer(idxn, 5); 2078 MatCheckPreallocated(mat, 1); 2079 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2080 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2081 if (PetscDefined(USE_DEBUG)) { 2082 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2083 PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2084 } 2085 if (PetscDefined(USE_DEBUG)) { 2086 PetscInt rbs, cbs, M, N, i; 2087 PetscCall(MatGetBlockSizes(mat, &rbs, &cbs)); 2088 PetscCall(MatGetSize(mat, &M, &N)); 2089 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); 2090 for (i = 0; i < n; i++) 2091 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); 2092 } 2093 if (mat->assembled) { 2094 mat->was_assembled = PETSC_TRUE; 2095 mat->assembled = PETSC_FALSE; 2096 } 2097 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2098 if (mat->ops->setvaluesblocked) { 2099 PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv); 2100 } else { 2101 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn; 2102 PetscInt i, j, bs, cbs; 2103 2104 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 2105 if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2106 iidxm = buf; 2107 iidxn = buf + m * bs; 2108 } else { 2109 PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc)); 2110 iidxm = bufr; 2111 iidxn = bufc; 2112 } 2113 for (i = 0; i < m; i++) { 2114 for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j; 2115 } 2116 if (m != n || bs != cbs || idxm != idxn) { 2117 for (i = 0; i < n; i++) { 2118 for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j; 2119 } 2120 } else iidxn = iidxm; 2121 PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv)); 2122 PetscCall(PetscFree2(bufr, bufc)); 2123 } 2124 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2125 PetscFunctionReturn(PETSC_SUCCESS); 2126 } 2127 2128 /*@ 2129 MatGetValues - Gets a block of local values from a matrix. 2130 2131 Not Collective; can only return values that are owned by the give process 2132 2133 Input Parameters: 2134 + mat - the matrix 2135 . v - a logically two-dimensional array for storing the values 2136 . m - the number of rows 2137 . idxm - the global indices of the rows 2138 . n - the number of columns 2139 - idxn - the global indices of the columns 2140 2141 Level: advanced 2142 2143 Notes: 2144 The user must allocate space (m*n `PetscScalar`s) for the values, `v`. 2145 The values, `v`, are then returned in a row-oriented format, 2146 analogous to that used by default in `MatSetValues()`. 2147 2148 `MatGetValues()` uses 0-based row and column numbers in 2149 Fortran as well as in C. 2150 2151 `MatGetValues()` requires that the matrix has been assembled 2152 with `MatAssemblyBegin()`/`MatAssemblyEnd()`. Thus, calls to 2153 `MatSetValues()` and `MatGetValues()` CANNOT be made in succession 2154 without intermediate matrix assembly. 2155 2156 Negative row or column indices will be ignored and those locations in `v` will be 2157 left unchanged. 2158 2159 For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process. 2160 That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable 2161 from `MatGetOwnershipRange`(mat,&rstart,&rend). 2162 2163 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()` 2164 @*/ 2165 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) 2166 { 2167 PetscFunctionBegin; 2168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2169 PetscValidType(mat, 1); 2170 if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); 2171 PetscAssertPointer(idxm, 3); 2172 PetscAssertPointer(idxn, 5); 2173 PetscAssertPointer(v, 6); 2174 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2175 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2176 MatCheckPreallocated(mat, 1); 2177 2178 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2179 PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v); 2180 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2181 PetscFunctionReturn(PETSC_SUCCESS); 2182 } 2183 2184 /*@ 2185 MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices 2186 defined previously by `MatSetLocalToGlobalMapping()` 2187 2188 Not Collective 2189 2190 Input Parameters: 2191 + mat - the matrix 2192 . nrow - number of rows 2193 . irow - the row local indices 2194 . ncol - number of columns 2195 - icol - the column local indices 2196 2197 Output Parameter: 2198 . y - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 2199 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2200 2201 Level: advanced 2202 2203 Notes: 2204 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine. 2205 2206 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, 2207 are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can 2208 determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set 2209 with `MatSetLocalToGlobalMapping()`. 2210 2211 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2212 `MatSetValuesLocal()`, `MatGetValues()` 2213 @*/ 2214 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) 2215 { 2216 PetscFunctionBeginHot; 2217 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2218 PetscValidType(mat, 1); 2219 MatCheckPreallocated(mat, 1); 2220 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */ 2221 PetscAssertPointer(irow, 3); 2222 PetscAssertPointer(icol, 5); 2223 if (PetscDefined(USE_DEBUG)) { 2224 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2225 PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2226 } 2227 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2228 PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0)); 2229 if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y); 2230 else { 2231 PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm; 2232 if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2233 irowm = buf; 2234 icolm = buf + nrow; 2235 } else { 2236 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2237 irowm = bufr; 2238 icolm = bufc; 2239 } 2240 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping())."); 2241 PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping())."); 2242 PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm)); 2243 PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm)); 2244 PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y)); 2245 PetscCall(PetscFree2(bufr, bufc)); 2246 } 2247 PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0)); 2248 PetscFunctionReturn(PETSC_SUCCESS); 2249 } 2250 2251 /*@ 2252 MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and 2253 the same size. Currently, this can only be called once and creates the given matrix. 2254 2255 Not Collective 2256 2257 Input Parameters: 2258 + mat - the matrix 2259 . nb - the number of blocks 2260 . bs - the number of rows (and columns) in each block 2261 . rows - a concatenation of the rows for each block 2262 - v - a concatenation of logically two-dimensional arrays of values 2263 2264 Level: advanced 2265 2266 Notes: 2267 `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values 2268 2269 In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix. 2270 2271 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`, 2272 `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()` 2273 @*/ 2274 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) 2275 { 2276 PetscFunctionBegin; 2277 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2278 PetscValidType(mat, 1); 2279 PetscAssertPointer(rows, 4); 2280 PetscAssertPointer(v, 5); 2281 PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2282 2283 PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0)); 2284 if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v); 2285 else { 2286 for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES)); 2287 } 2288 PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0)); 2289 PetscFunctionReturn(PETSC_SUCCESS); 2290 } 2291 2292 /*@ 2293 MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by 2294 the routine `MatSetValuesLocal()` to allow users to insert matrix entries 2295 using a local (per-processor) numbering. 2296 2297 Not Collective 2298 2299 Input Parameters: 2300 + x - the matrix 2301 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()` 2302 - cmapping - column mapping 2303 2304 Level: intermediate 2305 2306 Note: 2307 If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix 2308 2309 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()` 2310 @*/ 2311 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) 2312 { 2313 PetscFunctionBegin; 2314 PetscValidHeaderSpecific(x, MAT_CLASSID, 1); 2315 PetscValidType(x, 1); 2316 if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2); 2317 if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3); 2318 if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping); 2319 else { 2320 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping)); 2321 PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping)); 2322 } 2323 PetscFunctionReturn(PETSC_SUCCESS); 2324 } 2325 2326 /*@ 2327 MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()` 2328 2329 Not Collective 2330 2331 Input Parameter: 2332 . A - the matrix 2333 2334 Output Parameters: 2335 + rmapping - row mapping 2336 - cmapping - column mapping 2337 2338 Level: advanced 2339 2340 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()` 2341 @*/ 2342 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) 2343 { 2344 PetscFunctionBegin; 2345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2346 PetscValidType(A, 1); 2347 if (rmapping) { 2348 PetscAssertPointer(rmapping, 2); 2349 *rmapping = A->rmap->mapping; 2350 } 2351 if (cmapping) { 2352 PetscAssertPointer(cmapping, 3); 2353 *cmapping = A->cmap->mapping; 2354 } 2355 PetscFunctionReturn(PETSC_SUCCESS); 2356 } 2357 2358 /*@ 2359 MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix 2360 2361 Logically Collective 2362 2363 Input Parameters: 2364 + A - the matrix 2365 . rmap - row layout 2366 - cmap - column layout 2367 2368 Level: advanced 2369 2370 Note: 2371 The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called. 2372 2373 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()` 2374 @*/ 2375 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) 2376 { 2377 PetscFunctionBegin; 2378 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2379 PetscCall(PetscLayoutReference(rmap, &A->rmap)); 2380 PetscCall(PetscLayoutReference(cmap, &A->cmap)); 2381 PetscFunctionReturn(PETSC_SUCCESS); 2382 } 2383 2384 /*@ 2385 MatGetLayouts - Gets the `PetscLayout` objects for rows and columns 2386 2387 Not Collective 2388 2389 Input Parameter: 2390 . A - the matrix 2391 2392 Output Parameters: 2393 + rmap - row layout 2394 - cmap - column layout 2395 2396 Level: advanced 2397 2398 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()` 2399 @*/ 2400 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) 2401 { 2402 PetscFunctionBegin; 2403 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 2404 PetscValidType(A, 1); 2405 if (rmap) { 2406 PetscAssertPointer(rmap, 2); 2407 *rmap = A->rmap; 2408 } 2409 if (cmap) { 2410 PetscAssertPointer(cmap, 3); 2411 *cmap = A->cmap; 2412 } 2413 PetscFunctionReturn(PETSC_SUCCESS); 2414 } 2415 2416 /*@ 2417 MatSetValuesLocal - Inserts or adds values into certain locations of a matrix, 2418 using a local numbering of the rows and columns. 2419 2420 Not Collective 2421 2422 Input Parameters: 2423 + mat - the matrix 2424 . nrow - number of rows 2425 . irow - the row local indices 2426 . ncol - number of columns 2427 . icol - the column local indices 2428 . y - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 2429 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2430 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2431 2432 Level: intermediate 2433 2434 Notes: 2435 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine 2436 2437 Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2438 options cannot be mixed without intervening calls to the assembly 2439 routines. 2440 2441 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2442 MUST be called after all calls to `MatSetValuesLocal()` have been completed. 2443 2444 Fortran Notes: 2445 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2446 .vb 2447 call MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2448 .ve 2449 2450 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2451 2452 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`, 2453 `MatGetValuesLocal()` 2454 @*/ 2455 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2456 { 2457 PetscFunctionBeginHot; 2458 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2459 PetscValidType(mat, 1); 2460 MatCheckPreallocated(mat, 1); 2461 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2462 PetscAssertPointer(irow, 3); 2463 PetscAssertPointer(icol, 5); 2464 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2465 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2466 if (PetscDefined(USE_DEBUG)) { 2467 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2468 PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2469 } 2470 2471 if (mat->assembled) { 2472 mat->was_assembled = PETSC_TRUE; 2473 mat->assembled = PETSC_FALSE; 2474 } 2475 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2476 if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv); 2477 else { 2478 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2479 const PetscInt *irowm, *icolm; 2480 2481 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) { 2482 bufr = buf; 2483 bufc = buf + nrow; 2484 irowm = bufr; 2485 icolm = bufc; 2486 } else { 2487 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2488 irowm = bufr; 2489 icolm = bufc; 2490 } 2491 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr)); 2492 else irowm = irow; 2493 if (mat->cmap->mapping) { 2494 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc)); 2495 else icolm = irowm; 2496 } else icolm = icol; 2497 PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv)); 2498 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2499 } 2500 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2501 PetscFunctionReturn(PETSC_SUCCESS); 2502 } 2503 2504 /*@ 2505 MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix, 2506 using a local ordering of the nodes a block at a time. 2507 2508 Not Collective 2509 2510 Input Parameters: 2511 + mat - the matrix 2512 . nrow - number of rows 2513 . irow - the row local indices 2514 . ncol - number of columns 2515 . icol - the column local indices 2516 . y - a one-dimensional array that contains the values implicitly stored as a two-dimensional array, by default in row-major order. 2517 See `MAT_ROW_ORIENTED` in `MatSetOption()` for how to use column-major order. 2518 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values 2519 2520 Level: intermediate 2521 2522 Notes: 2523 If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()` 2524 before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the 2525 2526 Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES` 2527 options cannot be mixed without intervening calls to the assembly 2528 routines. 2529 2530 These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()` 2531 MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed. 2532 2533 Fortran Notes: 2534 If any of `irow`, `icol`, and `y` are scalars pass them using, for example, 2535 .vb 2536 call MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES, ierr) 2537 .ve 2538 2539 If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array 2540 2541 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, 2542 `MatSetValuesLocal()`, `MatSetValuesBlocked()` 2543 @*/ 2544 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) 2545 { 2546 PetscFunctionBeginHot; 2547 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2548 PetscValidType(mat, 1); 2549 MatCheckPreallocated(mat, 1); 2550 if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */ 2551 PetscAssertPointer(irow, 3); 2552 PetscAssertPointer(icol, 5); 2553 if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 2554 else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values"); 2555 if (PetscDefined(USE_DEBUG)) { 2556 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2557 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); 2558 } 2559 2560 if (mat->assembled) { 2561 mat->was_assembled = PETSC_TRUE; 2562 mat->assembled = PETSC_FALSE; 2563 } 2564 if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */ 2565 PetscInt irbs, rbs; 2566 PetscCall(MatGetBlockSizes(mat, &rbs, NULL)); 2567 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs)); 2568 PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs); 2569 } 2570 if (PetscUnlikelyDebug(mat->cmap->mapping)) { 2571 PetscInt icbs, cbs; 2572 PetscCall(MatGetBlockSizes(mat, NULL, &cbs)); 2573 PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs)); 2574 PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs); 2575 } 2576 PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0)); 2577 if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv); 2578 else { 2579 PetscInt buf[8192], *bufr = NULL, *bufc = NULL; 2580 const PetscInt *irowm, *icolm; 2581 2582 if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) { 2583 bufr = buf; 2584 bufc = buf + nrow; 2585 irowm = bufr; 2586 icolm = bufc; 2587 } else { 2588 PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc)); 2589 irowm = bufr; 2590 icolm = bufc; 2591 } 2592 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr)); 2593 else irowm = irow; 2594 if (mat->cmap->mapping) { 2595 if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc)); 2596 else icolm = irowm; 2597 } else icolm = icol; 2598 PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv)); 2599 if (bufr != buf) PetscCall(PetscFree2(bufr, bufc)); 2600 } 2601 PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0)); 2602 PetscFunctionReturn(PETSC_SUCCESS); 2603 } 2604 2605 /*@ 2606 MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal 2607 2608 Collective 2609 2610 Input Parameters: 2611 + mat - the matrix 2612 - x - the vector to be multiplied 2613 2614 Output Parameter: 2615 . y - the result 2616 2617 Level: developer 2618 2619 Note: 2620 The vectors `x` and `y` cannot be the same. I.e., one cannot 2621 call `MatMultDiagonalBlock`(A,y,y). 2622 2623 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2624 @*/ 2625 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) 2626 { 2627 PetscFunctionBegin; 2628 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2629 PetscValidType(mat, 1); 2630 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2631 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2632 2633 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2634 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2635 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2636 MatCheckPreallocated(mat, 1); 2637 2638 PetscUseTypeMethod(mat, multdiagonalblock, x, y); 2639 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2640 PetscFunctionReturn(PETSC_SUCCESS); 2641 } 2642 2643 /*@ 2644 MatMult - Computes the matrix-vector product, $y = Ax$. 2645 2646 Neighbor-wise Collective 2647 2648 Input Parameters: 2649 + mat - the matrix 2650 - x - the vector to be multiplied 2651 2652 Output Parameter: 2653 . y - the result 2654 2655 Level: beginner 2656 2657 Note: 2658 The vectors `x` and `y` cannot be the same. I.e., one cannot 2659 call `MatMult`(A,y,y). 2660 2661 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 2662 @*/ 2663 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) 2664 { 2665 PetscFunctionBegin; 2666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2667 PetscValidType(mat, 1); 2668 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2669 VecCheckAssembled(x); 2670 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2671 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2672 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2673 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2674 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); 2675 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); 2676 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); 2677 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); 2678 PetscCall(VecSetErrorIfLocked(y, 3)); 2679 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2680 MatCheckPreallocated(mat, 1); 2681 2682 PetscCall(VecLockReadPush(x)); 2683 PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0)); 2684 PetscUseTypeMethod(mat, mult, x, y); 2685 PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0)); 2686 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2687 PetscCall(VecLockReadPop(x)); 2688 PetscFunctionReturn(PETSC_SUCCESS); 2689 } 2690 2691 /*@ 2692 MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$. 2693 2694 Neighbor-wise Collective 2695 2696 Input Parameters: 2697 + mat - the matrix 2698 - x - the vector to be multiplied 2699 2700 Output Parameter: 2701 . y - the result 2702 2703 Level: beginner 2704 2705 Notes: 2706 The vectors `x` and `y` cannot be the same. I.e., one cannot 2707 call `MatMultTranspose`(A,y,y). 2708 2709 For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple, 2710 use `MatMultHermitianTranspose()` 2711 2712 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()` 2713 @*/ 2714 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) 2715 { 2716 PetscErrorCode (*op)(Mat, Vec, Vec) = NULL; 2717 2718 PetscFunctionBegin; 2719 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2720 PetscValidType(mat, 1); 2721 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2722 VecCheckAssembled(x); 2723 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2724 2725 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2726 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2727 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2728 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); 2729 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); 2730 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); 2731 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); 2732 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE)); 2733 MatCheckPreallocated(mat, 1); 2734 2735 if (!mat->ops->multtranspose) { 2736 if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult; 2737 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); 2738 } else op = mat->ops->multtranspose; 2739 PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0)); 2740 PetscCall(VecLockReadPush(x)); 2741 PetscCall((*op)(mat, x, y)); 2742 PetscCall(VecLockReadPop(x)); 2743 PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0)); 2744 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2745 if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE)); 2746 PetscFunctionReturn(PETSC_SUCCESS); 2747 } 2748 2749 /*@ 2750 MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$. 2751 2752 Neighbor-wise Collective 2753 2754 Input Parameters: 2755 + mat - the matrix 2756 - x - the vector to be multiplied 2757 2758 Output Parameter: 2759 . y - the result 2760 2761 Level: beginner 2762 2763 Notes: 2764 The vectors `x` and `y` cannot be the same. I.e., one cannot 2765 call `MatMultHermitianTranspose`(A,y,y). 2766 2767 Also called the conjugate transpose, complex conjugate transpose, or adjoint. 2768 2769 For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical. 2770 2771 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()` 2772 @*/ 2773 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) 2774 { 2775 PetscFunctionBegin; 2776 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2777 PetscValidType(mat, 1); 2778 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 2779 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 2780 2781 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2782 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2783 PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors"); 2784 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); 2785 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); 2786 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); 2787 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); 2788 MatCheckPreallocated(mat, 1); 2789 2790 PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0)); 2791 #if defined(PETSC_USE_COMPLEX) 2792 if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) { 2793 PetscCall(VecLockReadPush(x)); 2794 if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y); 2795 else PetscUseTypeMethod(mat, mult, x, y); 2796 PetscCall(VecLockReadPop(x)); 2797 } else { 2798 Vec w; 2799 PetscCall(VecDuplicate(x, &w)); 2800 PetscCall(VecCopy(x, w)); 2801 PetscCall(VecConjugate(w)); 2802 PetscCall(MatMultTranspose(mat, w, y)); 2803 PetscCall(VecDestroy(&w)); 2804 PetscCall(VecConjugate(y)); 2805 } 2806 PetscCall(PetscObjectStateIncrease((PetscObject)y)); 2807 #else 2808 PetscCall(MatMultTranspose(mat, x, y)); 2809 #endif 2810 PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0)); 2811 PetscFunctionReturn(PETSC_SUCCESS); 2812 } 2813 2814 /*@ 2815 MatMultAdd - Computes $v3 = v2 + A * v1$. 2816 2817 Neighbor-wise Collective 2818 2819 Input Parameters: 2820 + mat - the matrix 2821 . v1 - the vector to be multiplied by `mat` 2822 - v2 - the vector to be added to the result 2823 2824 Output Parameter: 2825 . v3 - the result 2826 2827 Level: beginner 2828 2829 Note: 2830 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2831 call `MatMultAdd`(A,v1,v2,v1). 2832 2833 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()` 2834 @*/ 2835 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2836 { 2837 PetscFunctionBegin; 2838 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2839 PetscValidType(mat, 1); 2840 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2841 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2842 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2843 2844 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2845 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2846 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); 2847 /* 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); 2848 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); */ 2849 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); 2850 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); 2851 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2852 MatCheckPreallocated(mat, 1); 2853 2854 PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3)); 2855 PetscCall(VecLockReadPush(v1)); 2856 PetscUseTypeMethod(mat, multadd, v1, v2, v3); 2857 PetscCall(VecLockReadPop(v1)); 2858 PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3)); 2859 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2860 PetscFunctionReturn(PETSC_SUCCESS); 2861 } 2862 2863 /*@ 2864 MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$. 2865 2866 Neighbor-wise Collective 2867 2868 Input Parameters: 2869 + mat - the matrix 2870 . v1 - the vector to be multiplied by the transpose of the matrix 2871 - v2 - the vector to be added to the result 2872 2873 Output Parameter: 2874 . v3 - the result 2875 2876 Level: beginner 2877 2878 Note: 2879 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2880 call `MatMultTransposeAdd`(A,v1,v2,v1). 2881 2882 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2883 @*/ 2884 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2885 { 2886 PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd; 2887 2888 PetscFunctionBegin; 2889 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2890 PetscValidType(mat, 1); 2891 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2892 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2893 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2894 2895 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2896 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2897 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); 2898 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); 2899 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); 2900 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2901 PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name); 2902 MatCheckPreallocated(mat, 1); 2903 2904 PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2905 PetscCall(VecLockReadPush(v1)); 2906 PetscCall((*op)(mat, v1, v2, v3)); 2907 PetscCall(VecLockReadPop(v1)); 2908 PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3)); 2909 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2910 PetscFunctionReturn(PETSC_SUCCESS); 2911 } 2912 2913 /*@ 2914 MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$. 2915 2916 Neighbor-wise Collective 2917 2918 Input Parameters: 2919 + mat - the matrix 2920 . v1 - the vector to be multiplied by the Hermitian transpose 2921 - v2 - the vector to be added to the result 2922 2923 Output Parameter: 2924 . v3 - the result 2925 2926 Level: beginner 2927 2928 Note: 2929 The vectors `v1` and `v3` cannot be the same. I.e., one cannot 2930 call `MatMultHermitianTransposeAdd`(A,v1,v2,v1). 2931 2932 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()` 2933 @*/ 2934 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) 2935 { 2936 PetscFunctionBegin; 2937 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2938 PetscValidType(mat, 1); 2939 PetscValidHeaderSpecific(v1, VEC_CLASSID, 2); 2940 PetscValidHeaderSpecific(v2, VEC_CLASSID, 3); 2941 PetscValidHeaderSpecific(v3, VEC_CLASSID, 4); 2942 2943 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2944 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2945 PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors"); 2946 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); 2947 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); 2948 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); 2949 MatCheckPreallocated(mat, 1); 2950 2951 PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2952 PetscCall(VecLockReadPush(v1)); 2953 if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3); 2954 else { 2955 Vec w, z; 2956 PetscCall(VecDuplicate(v1, &w)); 2957 PetscCall(VecCopy(v1, w)); 2958 PetscCall(VecConjugate(w)); 2959 PetscCall(VecDuplicate(v3, &z)); 2960 PetscCall(MatMultTranspose(mat, w, z)); 2961 PetscCall(VecDestroy(&w)); 2962 PetscCall(VecConjugate(z)); 2963 if (v2 != v3) { 2964 PetscCall(VecWAXPY(v3, 1.0, v2, z)); 2965 } else { 2966 PetscCall(VecAXPY(v3, 1.0, z)); 2967 } 2968 PetscCall(VecDestroy(&z)); 2969 } 2970 PetscCall(VecLockReadPop(v1)); 2971 PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3)); 2972 PetscCall(PetscObjectStateIncrease((PetscObject)v3)); 2973 PetscFunctionReturn(PETSC_SUCCESS); 2974 } 2975 2976 /*@ 2977 MatGetFactorType - gets the type of factorization a matrix is 2978 2979 Not Collective 2980 2981 Input Parameter: 2982 . mat - the matrix 2983 2984 Output Parameter: 2985 . 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` 2986 2987 Level: intermediate 2988 2989 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 2990 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 2991 @*/ 2992 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) 2993 { 2994 PetscFunctionBegin; 2995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 2996 PetscValidType(mat, 1); 2997 PetscAssertPointer(t, 2); 2998 *t = mat->factortype; 2999 PetscFunctionReturn(PETSC_SUCCESS); 3000 } 3001 3002 /*@ 3003 MatSetFactorType - sets the type of factorization a matrix is 3004 3005 Logically Collective 3006 3007 Input Parameters: 3008 + mat - the matrix 3009 - 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` 3010 3011 Level: intermediate 3012 3013 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, 3014 `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR` 3015 @*/ 3016 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) 3017 { 3018 PetscFunctionBegin; 3019 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3020 PetscValidType(mat, 1); 3021 mat->factortype = t; 3022 PetscFunctionReturn(PETSC_SUCCESS); 3023 } 3024 3025 /*@ 3026 MatGetInfo - Returns information about matrix storage (number of 3027 nonzeros, memory, etc.). 3028 3029 Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag 3030 3031 Input Parameters: 3032 + mat - the matrix 3033 - 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) 3034 3035 Output Parameter: 3036 . info - matrix information context 3037 3038 Options Database Key: 3039 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT` 3040 3041 Level: intermediate 3042 3043 Notes: 3044 The `MatInfo` context contains a variety of matrix data, including 3045 number of nonzeros allocated and used, number of mallocs during 3046 matrix assembly, etc. Additional information for factored matrices 3047 is provided (such as the fill ratio, number of mallocs during 3048 factorization, etc.). 3049 3050 Example: 3051 See the file ${PETSC_DIR}/include/petscmat.h for a complete list of 3052 data within the `MatInfo` context. For example, 3053 .vb 3054 MatInfo info; 3055 Mat A; 3056 double mal, nz_a, nz_u; 3057 3058 MatGetInfo(A, MAT_LOCAL, &info); 3059 mal = info.mallocs; 3060 nz_a = info.nz_allocated; 3061 .ve 3062 3063 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()` 3064 @*/ 3065 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) 3066 { 3067 PetscFunctionBegin; 3068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3069 PetscValidType(mat, 1); 3070 PetscAssertPointer(info, 3); 3071 MatCheckPreallocated(mat, 1); 3072 PetscUseTypeMethod(mat, getinfo, flag, info); 3073 PetscFunctionReturn(PETSC_SUCCESS); 3074 } 3075 3076 /* 3077 This is used by external packages where it is not easy to get the info from the actual 3078 matrix factorization. 3079 */ 3080 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) 3081 { 3082 PetscFunctionBegin; 3083 PetscCall(PetscMemzero(info, sizeof(MatInfo))); 3084 PetscFunctionReturn(PETSC_SUCCESS); 3085 } 3086 3087 /*@ 3088 MatLUFactor - Performs in-place LU factorization of matrix. 3089 3090 Collective 3091 3092 Input Parameters: 3093 + mat - the matrix 3094 . row - row permutation 3095 . col - column permutation 3096 - info - options for factorization, includes 3097 .vb 3098 fill - expected fill as ratio of original fill. 3099 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3100 Run with the option -info to determine an optimal value to use 3101 .ve 3102 3103 Level: developer 3104 3105 Notes: 3106 Most users should employ the `KSP` interface for linear solvers 3107 instead of working directly with matrix algebra routines such as this. 3108 See, e.g., `KSPCreate()`. 3109 3110 This changes the state of the matrix to a factored matrix; it cannot be used 3111 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3112 3113 This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()` 3114 when not using `KSP`. 3115 3116 Fortran Note: 3117 A valid (non-null) `info` argument must be provided 3118 3119 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, 3120 `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()` 3121 @*/ 3122 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3123 { 3124 MatFactorInfo tinfo; 3125 3126 PetscFunctionBegin; 3127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3128 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3129 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3130 if (info) PetscAssertPointer(info, 4); 3131 PetscValidType(mat, 1); 3132 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3133 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3134 MatCheckPreallocated(mat, 1); 3135 if (!info) { 3136 PetscCall(MatFactorInfoInitialize(&tinfo)); 3137 info = &tinfo; 3138 } 3139 3140 PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0)); 3141 PetscUseTypeMethod(mat, lufactor, row, col, info); 3142 PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0)); 3143 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3144 PetscFunctionReturn(PETSC_SUCCESS); 3145 } 3146 3147 /*@ 3148 MatILUFactor - Performs in-place ILU factorization of matrix. 3149 3150 Collective 3151 3152 Input Parameters: 3153 + mat - the matrix 3154 . row - row permutation 3155 . col - column permutation 3156 - info - structure containing 3157 .vb 3158 levels - number of levels of fill. 3159 expected fill - as ratio of original fill. 3160 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 3161 missing diagonal entries) 3162 .ve 3163 3164 Level: developer 3165 3166 Notes: 3167 Most users should employ the `KSP` interface for linear solvers 3168 instead of working directly with matrix algebra routines such as this. 3169 See, e.g., `KSPCreate()`. 3170 3171 Probably really in-place only when level of fill is zero, otherwise allocates 3172 new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()` 3173 when not using `KSP`. 3174 3175 Fortran Note: 3176 A valid (non-null) `info` argument must be provided 3177 3178 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 3179 @*/ 3180 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) 3181 { 3182 PetscFunctionBegin; 3183 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3184 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 3185 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3186 PetscAssertPointer(info, 4); 3187 PetscValidType(mat, 1); 3188 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 3189 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3190 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3191 MatCheckPreallocated(mat, 1); 3192 3193 PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0)); 3194 PetscUseTypeMethod(mat, ilufactor, row, col, info); 3195 PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0)); 3196 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3197 PetscFunctionReturn(PETSC_SUCCESS); 3198 } 3199 3200 /*@ 3201 MatLUFactorSymbolic - Performs symbolic LU factorization of matrix. 3202 Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`. 3203 3204 Collective 3205 3206 Input Parameters: 3207 + fact - the factor matrix obtained with `MatGetFactor()` 3208 . mat - the matrix 3209 . row - the row permutation 3210 . col - the column permutation 3211 - info - options for factorization, includes 3212 .vb 3213 fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use 3214 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3215 .ve 3216 3217 Level: developer 3218 3219 Notes: 3220 See [Matrix Factorization](sec_matfactor) for additional information about factorizations 3221 3222 Most users should employ the simplified `KSP` interface for linear solvers 3223 instead of working directly with matrix algebra routines such as this. 3224 See, e.g., `KSPCreate()`. 3225 3226 Fortran Note: 3227 A valid (non-null) `info` argument must be provided 3228 3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()` 3230 @*/ 3231 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 3232 { 3233 MatFactorInfo tinfo; 3234 3235 PetscFunctionBegin; 3236 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3238 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 3239 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 3240 if (info) PetscAssertPointer(info, 5); 3241 PetscValidType(fact, 1); 3242 PetscValidType(mat, 2); 3243 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3244 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3245 MatCheckPreallocated(mat, 2); 3246 if (!info) { 3247 PetscCall(MatFactorInfoInitialize(&tinfo)); 3248 info = &tinfo; 3249 } 3250 3251 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0)); 3252 PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info); 3253 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0)); 3254 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3255 PetscFunctionReturn(PETSC_SUCCESS); 3256 } 3257 3258 /*@ 3259 MatLUFactorNumeric - Performs numeric LU factorization of a matrix. 3260 Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`. 3261 3262 Collective 3263 3264 Input Parameters: 3265 + fact - the factor matrix obtained with `MatGetFactor()` 3266 . mat - the matrix 3267 - info - options for factorization 3268 3269 Level: developer 3270 3271 Notes: 3272 See `MatLUFactor()` for in-place factorization. See 3273 `MatCholeskyFactorNumeric()` for the symmetric, positive definite case. 3274 3275 Most users should employ the `KSP` interface for linear solvers 3276 instead of working directly with matrix algebra routines such as this. 3277 See, e.g., `KSPCreate()`. 3278 3279 Fortran Note: 3280 A valid (non-null) `info` argument must be provided 3281 3282 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()` 3283 @*/ 3284 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3285 { 3286 MatFactorInfo tinfo; 3287 3288 PetscFunctionBegin; 3289 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3291 PetscValidType(fact, 1); 3292 PetscValidType(mat, 2); 3293 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3294 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, 3295 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3296 3297 MatCheckPreallocated(mat, 2); 3298 if (!info) { 3299 PetscCall(MatFactorInfoInitialize(&tinfo)); 3300 info = &tinfo; 3301 } 3302 3303 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3304 else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0)); 3305 PetscUseTypeMethod(fact, lufactornumeric, mat, info); 3306 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0)); 3307 else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0)); 3308 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3309 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3310 PetscFunctionReturn(PETSC_SUCCESS); 3311 } 3312 3313 /*@ 3314 MatCholeskyFactor - Performs in-place Cholesky factorization of a 3315 symmetric matrix. 3316 3317 Collective 3318 3319 Input Parameters: 3320 + mat - the matrix 3321 . perm - row and column permutations 3322 - info - expected fill as ratio of original fill 3323 3324 Level: developer 3325 3326 Notes: 3327 See `MatLUFactor()` for the nonsymmetric case. See also `MatGetFactor()`, 3328 `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`. 3329 3330 Most users should employ the `KSP` interface for linear solvers 3331 instead of working directly with matrix algebra routines such as this. 3332 See, e.g., `KSPCreate()`. 3333 3334 Fortran Note: 3335 A valid (non-null) `info` argument must be provided 3336 3337 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()` 3338 `MatGetOrdering()` 3339 @*/ 3340 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) 3341 { 3342 MatFactorInfo tinfo; 3343 3344 PetscFunctionBegin; 3345 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3346 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2); 3347 if (info) PetscAssertPointer(info, 3); 3348 PetscValidType(mat, 1); 3349 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3350 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3351 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3352 MatCheckPreallocated(mat, 1); 3353 if (!info) { 3354 PetscCall(MatFactorInfoInitialize(&tinfo)); 3355 info = &tinfo; 3356 } 3357 3358 PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0)); 3359 PetscUseTypeMethod(mat, choleskyfactor, perm, info); 3360 PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0)); 3361 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3362 PetscFunctionReturn(PETSC_SUCCESS); 3363 } 3364 3365 /*@ 3366 MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization 3367 of a symmetric matrix. 3368 3369 Collective 3370 3371 Input Parameters: 3372 + fact - the factor matrix obtained with `MatGetFactor()` 3373 . mat - the matrix 3374 . perm - row and column permutations 3375 - info - options for factorization, includes 3376 .vb 3377 fill - expected fill as ratio of original fill. 3378 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3379 Run with the option -info to determine an optimal value to use 3380 .ve 3381 3382 Level: developer 3383 3384 Notes: 3385 See `MatLUFactorSymbolic()` for the nonsymmetric case. See also 3386 `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`. 3387 3388 Most users should employ the `KSP` interface for linear solvers 3389 instead of working directly with matrix algebra routines such as this. 3390 See, e.g., `KSPCreate()`. 3391 3392 Fortran Note: 3393 A valid (non-null) `info` argument must be provided 3394 3395 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()` 3396 `MatGetOrdering()` 3397 @*/ 3398 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 3399 { 3400 MatFactorInfo tinfo; 3401 3402 PetscFunctionBegin; 3403 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3404 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3405 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 3406 if (info) PetscAssertPointer(info, 4); 3407 PetscValidType(fact, 1); 3408 PetscValidType(mat, 2); 3409 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square"); 3410 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3411 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3412 MatCheckPreallocated(mat, 2); 3413 if (!info) { 3414 PetscCall(MatFactorInfoInitialize(&tinfo)); 3415 info = &tinfo; 3416 } 3417 3418 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3419 PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info); 3420 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0)); 3421 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3422 PetscFunctionReturn(PETSC_SUCCESS); 3423 } 3424 3425 /*@ 3426 MatCholeskyFactorNumeric - Performs numeric Cholesky factorization 3427 of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and 3428 `MatCholeskyFactorSymbolic()`. 3429 3430 Collective 3431 3432 Input Parameters: 3433 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored 3434 . mat - the initial matrix that is to be factored 3435 - info - options for factorization 3436 3437 Level: developer 3438 3439 Note: 3440 Most users should employ the `KSP` interface for linear solvers 3441 instead of working directly with matrix algebra routines such as this. 3442 See, e.g., `KSPCreate()`. 3443 3444 Fortran Note: 3445 A valid (non-null) `info` argument must be provided 3446 3447 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()` 3448 @*/ 3449 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3450 { 3451 MatFactorInfo tinfo; 3452 3453 PetscFunctionBegin; 3454 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3455 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3456 PetscValidType(fact, 1); 3457 PetscValidType(mat, 2); 3458 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3459 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, 3460 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3461 MatCheckPreallocated(mat, 2); 3462 if (!info) { 3463 PetscCall(MatFactorInfoInitialize(&tinfo)); 3464 info = &tinfo; 3465 } 3466 3467 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3468 else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0)); 3469 PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info); 3470 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0)); 3471 else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0)); 3472 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3473 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3474 PetscFunctionReturn(PETSC_SUCCESS); 3475 } 3476 3477 /*@ 3478 MatQRFactor - Performs in-place QR factorization of matrix. 3479 3480 Collective 3481 3482 Input Parameters: 3483 + mat - the matrix 3484 . col - column permutation 3485 - info - options for factorization, includes 3486 .vb 3487 fill - expected fill as ratio of original fill. 3488 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3489 Run with the option -info to determine an optimal value to use 3490 .ve 3491 3492 Level: developer 3493 3494 Notes: 3495 Most users should employ the `KSP` interface for linear solvers 3496 instead of working directly with matrix algebra routines such as this. 3497 See, e.g., `KSPCreate()`. 3498 3499 This changes the state of the matrix to a factored matrix; it cannot be used 3500 for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`. 3501 3502 Fortran Note: 3503 A valid (non-null) `info` argument must be provided 3504 3505 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`, 3506 `MatSetUnfactored()` 3507 @*/ 3508 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) 3509 { 3510 PetscFunctionBegin; 3511 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3512 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2); 3513 if (info) PetscAssertPointer(info, 3); 3514 PetscValidType(mat, 1); 3515 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3516 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3517 MatCheckPreallocated(mat, 1); 3518 PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0)); 3519 PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info)); 3520 PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0)); 3521 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 3522 PetscFunctionReturn(PETSC_SUCCESS); 3523 } 3524 3525 /*@ 3526 MatQRFactorSymbolic - Performs symbolic QR factorization of matrix. 3527 Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`. 3528 3529 Collective 3530 3531 Input Parameters: 3532 + fact - the factor matrix obtained with `MatGetFactor()` 3533 . mat - the matrix 3534 . col - column permutation 3535 - info - options for factorization, includes 3536 .vb 3537 fill - expected fill as ratio of original fill. 3538 dtcol - pivot tolerance (0 no pivot, 1 full column pivoting) 3539 Run with the option -info to determine an optimal value to use 3540 .ve 3541 3542 Level: developer 3543 3544 Note: 3545 Most users should employ the `KSP` interface for linear solvers 3546 instead of working directly with matrix algebra routines such as this. 3547 See, e.g., `KSPCreate()`. 3548 3549 Fortran Note: 3550 A valid (non-null) `info` argument must be provided 3551 3552 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()` 3553 @*/ 3554 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) 3555 { 3556 MatFactorInfo tinfo; 3557 3558 PetscFunctionBegin; 3559 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3560 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3561 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3); 3562 if (info) PetscAssertPointer(info, 4); 3563 PetscValidType(fact, 1); 3564 PetscValidType(mat, 2); 3565 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3566 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 3567 MatCheckPreallocated(mat, 2); 3568 if (!info) { 3569 PetscCall(MatFactorInfoInitialize(&tinfo)); 3570 info = &tinfo; 3571 } 3572 3573 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3574 PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info)); 3575 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0)); 3576 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3577 PetscFunctionReturn(PETSC_SUCCESS); 3578 } 3579 3580 /*@ 3581 MatQRFactorNumeric - Performs numeric QR factorization of a matrix. 3582 Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`. 3583 3584 Collective 3585 3586 Input Parameters: 3587 + fact - the factor matrix obtained with `MatGetFactor()` 3588 . mat - the matrix 3589 - info - options for factorization 3590 3591 Level: developer 3592 3593 Notes: 3594 See `MatQRFactor()` for in-place factorization. 3595 3596 Most users should employ the `KSP` interface for linear solvers 3597 instead of working directly with matrix algebra routines such as this. 3598 See, e.g., `KSPCreate()`. 3599 3600 Fortran Note: 3601 A valid (non-null) `info` argument must be provided 3602 3603 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()` 3604 @*/ 3605 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) 3606 { 3607 MatFactorInfo tinfo; 3608 3609 PetscFunctionBegin; 3610 PetscValidHeaderSpecific(fact, MAT_CLASSID, 1); 3611 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 3612 PetscValidType(fact, 1); 3613 PetscValidType(mat, 2); 3614 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 3615 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, 3616 mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N); 3617 3618 MatCheckPreallocated(mat, 2); 3619 if (!info) { 3620 PetscCall(MatFactorInfoInitialize(&tinfo)); 3621 info = &tinfo; 3622 } 3623 3624 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3625 else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0)); 3626 PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info)); 3627 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0)); 3628 else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0)); 3629 PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view")); 3630 PetscCall(PetscObjectStateIncrease((PetscObject)fact)); 3631 PetscFunctionReturn(PETSC_SUCCESS); 3632 } 3633 3634 /*@ 3635 MatSolve - Solves $A x = b$, given a factored matrix. 3636 3637 Neighbor-wise Collective 3638 3639 Input Parameters: 3640 + mat - the factored matrix 3641 - b - the right-hand-side vector 3642 3643 Output Parameter: 3644 . x - the result vector 3645 3646 Level: developer 3647 3648 Notes: 3649 The vectors `b` and `x` cannot be the same. I.e., one cannot 3650 call `MatSolve`(A,x,x). 3651 3652 Most users should employ the `KSP` interface for linear solvers 3653 instead of working directly with matrix algebra routines such as this. 3654 See, e.g., `KSPCreate()`. 3655 3656 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3657 @*/ 3658 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) 3659 { 3660 PetscFunctionBegin; 3661 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3662 PetscValidType(mat, 1); 3663 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3664 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3665 PetscCheckSameComm(mat, 1, b, 2); 3666 PetscCheckSameComm(mat, 1, x, 3); 3667 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3668 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); 3669 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); 3670 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); 3671 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3672 MatCheckPreallocated(mat, 1); 3673 3674 PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0)); 3675 PetscCall(VecFlag(x, mat->factorerrortype)); 3676 if (mat->factorerrortype) PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 3677 else PetscUseTypeMethod(mat, solve, b, x); 3678 PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0)); 3679 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3680 PetscFunctionReturn(PETSC_SUCCESS); 3681 } 3682 3683 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) 3684 { 3685 Vec b, x; 3686 PetscInt N, i; 3687 PetscErrorCode (*f)(Mat, Vec, Vec); 3688 PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE; 3689 3690 PetscFunctionBegin; 3691 if (A->factorerrortype) { 3692 PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype)); 3693 PetscCall(MatSetInf(X)); 3694 PetscFunctionReturn(PETSC_SUCCESS); 3695 } 3696 f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose; 3697 PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name); 3698 PetscCall(MatBoundToCPU(A, &Abound)); 3699 if (!Abound) { 3700 PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3701 PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, "")); 3702 } 3703 #if PetscDefined(HAVE_CUDA) 3704 if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B)); 3705 if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X)); 3706 #elif PetscDefined(HAVE_HIP) 3707 if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B)); 3708 if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X)); 3709 #endif 3710 PetscCall(MatGetSize(B, NULL, &N)); 3711 for (i = 0; i < N; i++) { 3712 PetscCall(MatDenseGetColumnVecRead(B, i, &b)); 3713 PetscCall(MatDenseGetColumnVecWrite(X, i, &x)); 3714 PetscCall((*f)(A, b, x)); 3715 PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x)); 3716 PetscCall(MatDenseRestoreColumnVecRead(B, i, &b)); 3717 } 3718 if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B)); 3719 if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X)); 3720 PetscFunctionReturn(PETSC_SUCCESS); 3721 } 3722 3723 /*@ 3724 MatMatSolve - Solves $A X = B$, given a factored matrix. 3725 3726 Neighbor-wise Collective 3727 3728 Input Parameters: 3729 + A - the factored matrix 3730 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS) 3731 3732 Output Parameter: 3733 . X - the result matrix (dense matrix) 3734 3735 Level: developer 3736 3737 Note: 3738 If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`; 3739 otherwise, `B` and `X` cannot be the same. 3740 3741 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3742 @*/ 3743 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) 3744 { 3745 PetscFunctionBegin; 3746 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3747 PetscValidType(A, 1); 3748 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3749 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3750 PetscCheckSameComm(A, 1, B, 2); 3751 PetscCheckSameComm(A, 1, X, 3); 3752 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); 3753 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); 3754 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"); 3755 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3756 MatCheckPreallocated(A, 1); 3757 3758 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3759 if (!A->ops->matsolve) { 3760 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name)); 3761 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE)); 3762 } else PetscUseTypeMethod(A, matsolve, B, X); 3763 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3764 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3765 PetscFunctionReturn(PETSC_SUCCESS); 3766 } 3767 3768 /*@ 3769 MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix. 3770 3771 Neighbor-wise Collective 3772 3773 Input Parameters: 3774 + A - the factored matrix 3775 - B - the right-hand-side matrix (`MATDENSE` matrix) 3776 3777 Output Parameter: 3778 . X - the result matrix (dense matrix) 3779 3780 Level: developer 3781 3782 Note: 3783 The matrices `B` and `X` cannot be the same. I.e., one cannot 3784 call `MatMatSolveTranspose`(A,X,X). 3785 3786 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()` 3787 @*/ 3788 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) 3789 { 3790 PetscFunctionBegin; 3791 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3792 PetscValidType(A, 1); 3793 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 3794 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3795 PetscCheckSameComm(A, 1, B, 2); 3796 PetscCheckSameComm(A, 1, X, 3); 3797 PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3798 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); 3799 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); 3800 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); 3801 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"); 3802 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3803 MatCheckPreallocated(A, 1); 3804 3805 PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0)); 3806 if (!A->ops->matsolvetranspose) { 3807 PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name)); 3808 PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE)); 3809 } else PetscUseTypeMethod(A, matsolvetranspose, B, X); 3810 PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0)); 3811 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3812 PetscFunctionReturn(PETSC_SUCCESS); 3813 } 3814 3815 /*@ 3816 MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix. 3817 3818 Neighbor-wise Collective 3819 3820 Input Parameters: 3821 + A - the factored matrix 3822 - Bt - the transpose of right-hand-side matrix as a `MATDENSE` 3823 3824 Output Parameter: 3825 . X - the result matrix (dense matrix) 3826 3827 Level: developer 3828 3829 Note: 3830 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 3831 format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`. 3832 3833 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()` 3834 @*/ 3835 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) 3836 { 3837 PetscFunctionBegin; 3838 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 3839 PetscValidType(A, 1); 3840 PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2); 3841 PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 3842 PetscCheckSameComm(A, 1, Bt, 2); 3843 PetscCheckSameComm(A, 1, X, 3); 3844 3845 PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices"); 3846 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); 3847 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); 3848 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"); 3849 if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3850 PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 3851 MatCheckPreallocated(A, 1); 3852 3853 PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0)); 3854 PetscUseTypeMethod(A, mattransposesolve, Bt, X); 3855 PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0)); 3856 PetscCall(PetscObjectStateIncrease((PetscObject)X)); 3857 PetscFunctionReturn(PETSC_SUCCESS); 3858 } 3859 3860 /*@ 3861 MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or 3862 $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3863 3864 Neighbor-wise Collective 3865 3866 Input Parameters: 3867 + mat - the factored matrix 3868 - b - the right-hand-side vector 3869 3870 Output Parameter: 3871 . x - the result vector 3872 3873 Level: developer 3874 3875 Notes: 3876 `MatSolve()` should be used for most applications, as it performs 3877 a forward solve followed by a backward solve. 3878 3879 The vectors `b` and `x` cannot be the same, i.e., one cannot 3880 call `MatForwardSolve`(A,x,x). 3881 3882 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3883 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3884 `MatForwardSolve()` solves $U^T*D y = b$, and 3885 `MatBackwardSolve()` solves $U x = y$. 3886 Thus they do not provide a symmetric preconditioner. 3887 3888 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()` 3889 @*/ 3890 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) 3891 { 3892 PetscFunctionBegin; 3893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3894 PetscValidType(mat, 1); 3895 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3896 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3897 PetscCheckSameComm(mat, 1, b, 2); 3898 PetscCheckSameComm(mat, 1, x, 3); 3899 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3900 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); 3901 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); 3902 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); 3903 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3904 MatCheckPreallocated(mat, 1); 3905 3906 PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0)); 3907 PetscUseTypeMethod(mat, forwardsolve, b, x); 3908 PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0)); 3909 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3910 PetscFunctionReturn(PETSC_SUCCESS); 3911 } 3912 3913 /*@ 3914 MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$. 3915 $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$, 3916 3917 Neighbor-wise Collective 3918 3919 Input Parameters: 3920 + mat - the factored matrix 3921 - b - the right-hand-side vector 3922 3923 Output Parameter: 3924 . x - the result vector 3925 3926 Level: developer 3927 3928 Notes: 3929 `MatSolve()` should be used for most applications, as it performs 3930 a forward solve followed by a backward solve. 3931 3932 The vectors `b` and `x` cannot be the same. I.e., one cannot 3933 call `MatBackwardSolve`(A,x,x). 3934 3935 For matrix in `MATSEQBAIJ` format with block size larger than 1, 3936 the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet. 3937 `MatForwardSolve()` solves $U^T*D y = b$, and 3938 `MatBackwardSolve()` solves $U x = y$. 3939 Thus they do not provide a symmetric preconditioner. 3940 3941 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()` 3942 @*/ 3943 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) 3944 { 3945 PetscFunctionBegin; 3946 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3947 PetscValidType(mat, 1); 3948 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3949 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 3950 PetscCheckSameComm(mat, 1, b, 2); 3951 PetscCheckSameComm(mat, 1, x, 3); 3952 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 3953 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); 3954 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); 3955 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); 3956 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 3957 MatCheckPreallocated(mat, 1); 3958 3959 PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0)); 3960 PetscUseTypeMethod(mat, backwardsolve, b, x); 3961 PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0)); 3962 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 3963 PetscFunctionReturn(PETSC_SUCCESS); 3964 } 3965 3966 /*@ 3967 MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix. 3968 3969 Neighbor-wise Collective 3970 3971 Input Parameters: 3972 + mat - the factored matrix 3973 . b - the right-hand-side vector 3974 - y - the vector to be added to 3975 3976 Output Parameter: 3977 . x - the result vector 3978 3979 Level: developer 3980 3981 Note: 3982 The vectors `b` and `x` cannot be the same. I.e., one cannot 3983 call `MatSolveAdd`(A,x,y,x). 3984 3985 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()` 3986 @*/ 3987 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) 3988 { 3989 PetscScalar one = 1.0; 3990 Vec tmp; 3991 3992 PetscFunctionBegin; 3993 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 3994 PetscValidType(mat, 1); 3995 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 3996 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 3997 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 3998 PetscCheckSameComm(mat, 1, b, 2); 3999 PetscCheckSameComm(mat, 1, y, 3); 4000 PetscCheckSameComm(mat, 1, x, 4); 4001 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4002 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); 4003 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); 4004 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); 4005 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); 4006 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); 4007 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4008 MatCheckPreallocated(mat, 1); 4009 4010 PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y)); 4011 PetscCall(VecFlag(x, mat->factorerrortype)); 4012 if (mat->factorerrortype) { 4013 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4014 } else if (mat->ops->solveadd) { 4015 PetscUseTypeMethod(mat, solveadd, b, y, x); 4016 } else { 4017 /* do the solve then the add manually */ 4018 if (x != y) { 4019 PetscCall(MatSolve(mat, b, x)); 4020 PetscCall(VecAXPY(x, one, y)); 4021 } else { 4022 PetscCall(VecDuplicate(x, &tmp)); 4023 PetscCall(VecCopy(x, tmp)); 4024 PetscCall(MatSolve(mat, b, x)); 4025 PetscCall(VecAXPY(x, one, tmp)); 4026 PetscCall(VecDestroy(&tmp)); 4027 } 4028 } 4029 PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y)); 4030 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4031 PetscFunctionReturn(PETSC_SUCCESS); 4032 } 4033 4034 /*@ 4035 MatSolveTranspose - Solves $A^T x = b$, given a factored matrix. 4036 4037 Neighbor-wise Collective 4038 4039 Input Parameters: 4040 + mat - the factored matrix 4041 - b - the right-hand-side vector 4042 4043 Output Parameter: 4044 . x - the result vector 4045 4046 Level: developer 4047 4048 Notes: 4049 The vectors `b` and `x` cannot be the same. I.e., one cannot 4050 call `MatSolveTranspose`(A,x,x). 4051 4052 Most users should employ the `KSP` interface for linear solvers 4053 instead of working directly with matrix algebra routines such as this. 4054 See, e.g., `KSPCreate()`. 4055 4056 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()` 4057 @*/ 4058 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) 4059 { 4060 PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose; 4061 4062 PetscFunctionBegin; 4063 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4064 PetscValidType(mat, 1); 4065 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4066 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 4067 PetscCheckSameComm(mat, 1, b, 2); 4068 PetscCheckSameComm(mat, 1, x, 3); 4069 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4070 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); 4071 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); 4072 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4073 MatCheckPreallocated(mat, 1); 4074 PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0)); 4075 PetscCall(VecFlag(x, mat->factorerrortype)); 4076 if (mat->factorerrortype) { 4077 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4078 } else { 4079 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name); 4080 PetscCall((*f)(mat, b, x)); 4081 } 4082 PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0)); 4083 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4084 PetscFunctionReturn(PETSC_SUCCESS); 4085 } 4086 4087 /*@ 4088 MatSolveTransposeAdd - Computes $x = y + A^{-T} b$ 4089 factored matrix. 4090 4091 Neighbor-wise Collective 4092 4093 Input Parameters: 4094 + mat - the factored matrix 4095 . b - the right-hand-side vector 4096 - y - the vector to be added to 4097 4098 Output Parameter: 4099 . x - the result vector 4100 4101 Level: developer 4102 4103 Note: 4104 The vectors `b` and `x` cannot be the same. I.e., one cannot 4105 call `MatSolveTransposeAdd`(A,x,y,x). 4106 4107 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()` 4108 @*/ 4109 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) 4110 { 4111 PetscScalar one = 1.0; 4112 Vec tmp; 4113 PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd; 4114 4115 PetscFunctionBegin; 4116 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4117 PetscValidType(mat, 1); 4118 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 4119 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4120 PetscValidHeaderSpecific(x, VEC_CLASSID, 4); 4121 PetscCheckSameComm(mat, 1, b, 2); 4122 PetscCheckSameComm(mat, 1, y, 3); 4123 PetscCheckSameComm(mat, 1, x, 4); 4124 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 4125 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); 4126 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); 4127 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); 4128 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); 4129 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 4130 MatCheckPreallocated(mat, 1); 4131 4132 PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y)); 4133 PetscCall(VecFlag(x, mat->factorerrortype)); 4134 if (mat->factorerrortype) { 4135 PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype)); 4136 } else if (f) { 4137 PetscCall((*f)(mat, b, y, x)); 4138 } else { 4139 /* do the solve then the add manually */ 4140 if (x != y) { 4141 PetscCall(MatSolveTranspose(mat, b, x)); 4142 PetscCall(VecAXPY(x, one, y)); 4143 } else { 4144 PetscCall(VecDuplicate(x, &tmp)); 4145 PetscCall(VecCopy(x, tmp)); 4146 PetscCall(MatSolveTranspose(mat, b, x)); 4147 PetscCall(VecAXPY(x, one, tmp)); 4148 PetscCall(VecDestroy(&tmp)); 4149 } 4150 } 4151 PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y)); 4152 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4153 PetscFunctionReturn(PETSC_SUCCESS); 4154 } 4155 4156 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 4157 /*@ 4158 MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps. 4159 4160 Neighbor-wise Collective 4161 4162 Input Parameters: 4163 + mat - the matrix 4164 . b - the right-hand side 4165 . omega - the relaxation factor 4166 . flag - flag indicating the type of SOR (see below) 4167 . shift - diagonal shift 4168 . its - the number of iterations 4169 - lits - the number of local iterations 4170 4171 Output Parameter: 4172 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess) 4173 4174 SOR Flags: 4175 + `SOR_FORWARD_SWEEP` - forward SOR 4176 . `SOR_BACKWARD_SWEEP` - backward SOR 4177 . `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR) 4178 . `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR 4179 . `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR 4180 . `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR 4181 . `SOR_EISENSTAT` - SOR with Eisenstat trick 4182 . `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies upper/lower triangular part of matrix to vector (with `omega`) 4183 - `SOR_ZERO_INITIAL_GUESS` - zero initial guess 4184 4185 Level: developer 4186 4187 Notes: 4188 `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and 4189 `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings 4190 on each processor. 4191 4192 Application programmers will not generally use `MatSOR()` directly, 4193 but instead will employ `PCSOR` or `PCEISENSTAT` 4194 4195 For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with inodes, this does a block SOR smoothing, otherwise it does a pointwise smoothing. 4196 For `MATAIJ` matrices with inodes, the block sizes are determined by the inode sizes, not the block size set with `MatSetBlockSize()` 4197 4198 Vectors `x` and `b` CANNOT be the same 4199 4200 The flags are implemented as bitwise inclusive or operations. 4201 For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`) 4202 to specify a zero initial guess for SSOR. 4203 4204 Developer Note: 4205 We should add block SOR support for `MATAIJ` matrices with block size set to greater than one and no inodes 4206 4207 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()` 4208 @*/ 4209 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) 4210 { 4211 PetscFunctionBegin; 4212 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4213 PetscValidType(mat, 1); 4214 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 4215 PetscValidHeaderSpecific(x, VEC_CLASSID, 8); 4216 PetscCheckSameComm(mat, 1, b, 2); 4217 PetscCheckSameComm(mat, 1, x, 8); 4218 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4219 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4220 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); 4221 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); 4222 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); 4223 PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its); 4224 PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits); 4225 PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same"); 4226 4227 MatCheckPreallocated(mat, 1); 4228 PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0)); 4229 PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x); 4230 PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0)); 4231 PetscCall(PetscObjectStateIncrease((PetscObject)x)); 4232 PetscFunctionReturn(PETSC_SUCCESS); 4233 } 4234 4235 /* 4236 Default matrix copy routine. 4237 */ 4238 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) 4239 { 4240 PetscInt i, rstart = 0, rend = 0, nz; 4241 const PetscInt *cwork; 4242 const PetscScalar *vwork; 4243 4244 PetscFunctionBegin; 4245 if (B->assembled) PetscCall(MatZeroEntries(B)); 4246 if (str == SAME_NONZERO_PATTERN) { 4247 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 4248 for (i = rstart; i < rend; i++) { 4249 PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork)); 4250 PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES)); 4251 PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork)); 4252 } 4253 } else { 4254 PetscCall(MatAYPX(B, 0.0, A, str)); 4255 } 4256 PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 4257 PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 4258 PetscFunctionReturn(PETSC_SUCCESS); 4259 } 4260 4261 /*@ 4262 MatCopy - Copies a matrix to another matrix. 4263 4264 Collective 4265 4266 Input Parameters: 4267 + A - the matrix 4268 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN` 4269 4270 Output Parameter: 4271 . B - where the copy is put 4272 4273 Level: intermediate 4274 4275 Notes: 4276 If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash. 4277 4278 `MatCopy()` copies the matrix entries of a matrix to another existing 4279 matrix (after first zeroing the second matrix). A related routine is 4280 `MatConvert()`, which first creates a new matrix and then copies the data. 4281 4282 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()` 4283 @*/ 4284 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) 4285 { 4286 PetscInt i; 4287 4288 PetscFunctionBegin; 4289 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4290 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 4291 PetscValidType(A, 1); 4292 PetscValidType(B, 2); 4293 PetscCheckSameComm(A, 1, B, 2); 4294 MatCheckPreallocated(B, 2); 4295 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4296 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4297 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, 4298 A->cmap->N, B->cmap->N); 4299 MatCheckPreallocated(A, 1); 4300 if (A == B) PetscFunctionReturn(PETSC_SUCCESS); 4301 4302 PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0)); 4303 if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str); 4304 else PetscCall(MatCopy_Basic(A, B, str)); 4305 4306 B->stencil.dim = A->stencil.dim; 4307 B->stencil.noc = A->stencil.noc; 4308 for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) { 4309 B->stencil.dims[i] = A->stencil.dims[i]; 4310 B->stencil.starts[i] = A->stencil.starts[i]; 4311 } 4312 4313 PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0)); 4314 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4315 PetscFunctionReturn(PETSC_SUCCESS); 4316 } 4317 4318 /*@ 4319 MatConvert - Converts a matrix to another matrix, either of the same 4320 or different type. 4321 4322 Collective 4323 4324 Input Parameters: 4325 + mat - the matrix 4326 . newtype - new matrix type. Use `MATSAME` to create a new matrix of the 4327 same type as the original matrix. 4328 - reuse - denotes if the destination matrix is to be created or reused. 4329 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 4330 `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). 4331 4332 Output Parameter: 4333 . M - pointer to place new matrix 4334 4335 Level: intermediate 4336 4337 Notes: 4338 `MatConvert()` first creates a new matrix and then copies the data from 4339 the first matrix. A related routine is `MatCopy()`, which copies the matrix 4340 entries of one matrix to another already existing matrix context. 4341 4342 Cannot be used to convert a sequential matrix to parallel or parallel to sequential, 4343 the MPI communicator of the generated matrix is always the same as the communicator 4344 of the input matrix. 4345 4346 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 4347 @*/ 4348 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) 4349 { 4350 PetscBool sametype, issame, flg; 4351 PetscBool3 issymmetric, ishermitian, isspd; 4352 char convname[256], mtype[256]; 4353 Mat B; 4354 4355 PetscFunctionBegin; 4356 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4357 PetscValidType(mat, 1); 4358 PetscAssertPointer(M, 4); 4359 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 4360 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4361 MatCheckPreallocated(mat, 1); 4362 4363 PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg)); 4364 if (flg) newtype = mtype; 4365 4366 PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype)); 4367 PetscCall(PetscStrcmp(newtype, "same", &issame)); 4368 PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix"); 4369 if (reuse == MAT_REUSE_MATRIX) { 4370 PetscValidHeaderSpecific(*M, MAT_CLASSID, 4); 4371 PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX"); 4372 } 4373 4374 if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) { 4375 PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4376 PetscFunctionReturn(PETSC_SUCCESS); 4377 } 4378 4379 /* Cache Mat options because some converters use MatHeaderReplace() */ 4380 issymmetric = mat->symmetric; 4381 ishermitian = mat->hermitian; 4382 isspd = mat->spd; 4383 4384 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4385 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4386 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4387 } else { 4388 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4389 const char *prefix[3] = {"seq", "mpi", ""}; 4390 PetscInt i; 4391 /* 4392 Order of precedence: 4393 0) See if newtype is a superclass of the current matrix. 4394 1) See if a specialized converter is known to the current matrix. 4395 2) See if a specialized converter is known to the desired matrix class. 4396 3) See if a good general converter is registered for the desired class 4397 (as of 6/27/03 only MATMPIADJ falls into this category). 4398 4) See if a good general converter is known for the current matrix. 4399 5) Use a really basic converter. 4400 */ 4401 4402 /* 0) See if newtype is a superclass of the current matrix. 4403 i.e mat is mpiaij and newtype is aij */ 4404 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4405 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4406 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4407 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4408 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4409 if (flg) { 4410 if (reuse == MAT_INPLACE_MATRIX) { 4411 PetscCall(PetscInfo(mat, "Early return\n")); 4412 PetscFunctionReturn(PETSC_SUCCESS); 4413 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4414 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4415 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4416 PetscFunctionReturn(PETSC_SUCCESS); 4417 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4418 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4419 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4420 PetscFunctionReturn(PETSC_SUCCESS); 4421 } 4422 } 4423 } 4424 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4425 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4426 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4427 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4428 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4429 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4430 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4431 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4432 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4433 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4434 if (conv) goto foundconv; 4435 } 4436 4437 /* 2) See if a specialized converter is known to the desired matrix class. */ 4438 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4439 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4440 PetscCall(MatSetType(B, newtype)); 4441 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4442 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4443 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4444 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4445 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4446 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4447 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4448 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4449 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4450 if (conv) { 4451 PetscCall(MatDestroy(&B)); 4452 goto foundconv; 4453 } 4454 } 4455 4456 /* 3) See if a good general converter is registered for the desired class */ 4457 conv = B->ops->convertfrom; 4458 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4459 PetscCall(MatDestroy(&B)); 4460 if (conv) goto foundconv; 4461 4462 /* 4) See if a good general converter is known for the current matrix */ 4463 if (mat->ops->convert) conv = mat->ops->convert; 4464 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4465 if (conv) goto foundconv; 4466 4467 /* 5) Use a really basic converter. */ 4468 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4469 conv = MatConvert_Basic; 4470 4471 foundconv: 4472 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4473 PetscCall((*conv)(mat, newtype, reuse, M)); 4474 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4475 /* the block sizes must be same if the mappings are copied over */ 4476 (*M)->rmap->bs = mat->rmap->bs; 4477 (*M)->cmap->bs = mat->cmap->bs; 4478 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4479 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4480 (*M)->rmap->mapping = mat->rmap->mapping; 4481 (*M)->cmap->mapping = mat->cmap->mapping; 4482 } 4483 (*M)->stencil.dim = mat->stencil.dim; 4484 (*M)->stencil.noc = mat->stencil.noc; 4485 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4486 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4487 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4488 } 4489 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4490 } 4491 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4492 4493 /* Reset Mat options */ 4494 if (issymmetric != PETSC_BOOL3_UNKNOWN) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PetscBool3ToBool(issymmetric))); 4495 if (ishermitian != PETSC_BOOL3_UNKNOWN) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PetscBool3ToBool(ishermitian))); 4496 if (isspd != PETSC_BOOL3_UNKNOWN) PetscCall(MatSetOption(*M, MAT_SPD, PetscBool3ToBool(isspd))); 4497 PetscFunctionReturn(PETSC_SUCCESS); 4498 } 4499 4500 /*@ 4501 MatFactorGetSolverType - Returns name of the package providing the factorization routines 4502 4503 Not Collective 4504 4505 Input Parameter: 4506 . mat - the matrix, must be a factored matrix 4507 4508 Output Parameter: 4509 . type - the string name of the package (do not free this string) 4510 4511 Level: intermediate 4512 4513 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()` 4514 @*/ 4515 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) 4516 { 4517 PetscErrorCode (*conv)(Mat, MatSolverType *); 4518 4519 PetscFunctionBegin; 4520 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4521 PetscValidType(mat, 1); 4522 PetscAssertPointer(type, 2); 4523 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 4524 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv)); 4525 if (conv) PetscCall((*conv)(mat, type)); 4526 else *type = MATSOLVERPETSC; 4527 PetscFunctionReturn(PETSC_SUCCESS); 4528 } 4529 4530 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType; 4531 struct _MatSolverTypeForSpecifcType { 4532 MatType mtype; 4533 /* no entry for MAT_FACTOR_NONE */ 4534 PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *); 4535 MatSolverTypeForSpecifcType next; 4536 }; 4537 4538 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder; 4539 struct _MatSolverTypeHolder { 4540 char *name; 4541 MatSolverTypeForSpecifcType handlers; 4542 MatSolverTypeHolder next; 4543 }; 4544 4545 static MatSolverTypeHolder MatSolverTypeHolders = NULL; 4546 4547 /*@C 4548 MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type 4549 4550 Logically Collective, No Fortran Support 4551 4552 Input Parameters: 4553 + package - name of the package, for example `petsc` or `superlu` 4554 . mtype - the matrix type that works with this package 4555 . ftype - the type of factorization supported by the package 4556 - createfactor - routine that will create the factored matrix ready to be used 4557 4558 Level: developer 4559 4560 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, 4561 `MatGetFactor()` 4562 @*/ 4563 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) 4564 { 4565 MatSolverTypeHolder next = MatSolverTypeHolders, prev = NULL; 4566 PetscBool flg; 4567 MatSolverTypeForSpecifcType inext, iprev = NULL; 4568 4569 PetscFunctionBegin; 4570 PetscCall(MatInitializePackage()); 4571 if (!next) { 4572 PetscCall(PetscNew(&MatSolverTypeHolders)); 4573 PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name)); 4574 PetscCall(PetscNew(&MatSolverTypeHolders->handlers)); 4575 PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype)); 4576 MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor; 4577 PetscFunctionReturn(PETSC_SUCCESS); 4578 } 4579 while (next) { 4580 PetscCall(PetscStrcasecmp(package, next->name, &flg)); 4581 if (flg) { 4582 PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers"); 4583 inext = next->handlers; 4584 while (inext) { 4585 PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg)); 4586 if (flg) { 4587 inext->createfactor[(int)ftype - 1] = createfactor; 4588 PetscFunctionReturn(PETSC_SUCCESS); 4589 } 4590 iprev = inext; 4591 inext = inext->next; 4592 } 4593 PetscCall(PetscNew(&iprev->next)); 4594 PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype)); 4595 iprev->next->createfactor[(int)ftype - 1] = createfactor; 4596 PetscFunctionReturn(PETSC_SUCCESS); 4597 } 4598 prev = next; 4599 next = next->next; 4600 } 4601 PetscCall(PetscNew(&prev->next)); 4602 PetscCall(PetscStrallocpy(package, &prev->next->name)); 4603 PetscCall(PetscNew(&prev->next->handlers)); 4604 PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype)); 4605 prev->next->handlers->createfactor[(int)ftype - 1] = createfactor; 4606 PetscFunctionReturn(PETSC_SUCCESS); 4607 } 4608 4609 /*@C 4610 MatSolverTypeGet - Gets the function that creates the factor matrix if it exist 4611 4612 Input Parameters: 4613 + 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 4614 . ftype - the type of factorization supported by the type 4615 - mtype - the matrix type that works with this type 4616 4617 Output Parameters: 4618 + foundtype - `PETSC_TRUE` if the type was registered 4619 . foundmtype - `PETSC_TRUE` if the type supports the requested mtype 4620 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found 4621 4622 Calling sequence of `createfactor`: 4623 + A - the matrix providing the factor matrix 4624 . ftype - the `MatFactorType` of the factor requested 4625 - B - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()` 4626 4627 Level: developer 4628 4629 Note: 4630 When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4631 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4632 For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`. 4633 4634 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`, 4635 `MatInitializePackage()` 4636 @*/ 4637 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B)) 4638 { 4639 MatSolverTypeHolder next = MatSolverTypeHolders; 4640 PetscBool flg; 4641 MatSolverTypeForSpecifcType inext; 4642 4643 PetscFunctionBegin; 4644 if (foundtype) *foundtype = PETSC_FALSE; 4645 if (foundmtype) *foundmtype = PETSC_FALSE; 4646 if (createfactor) *createfactor = NULL; 4647 4648 if (type) { 4649 while (next) { 4650 PetscCall(PetscStrcasecmp(type, next->name, &flg)); 4651 if (flg) { 4652 if (foundtype) *foundtype = PETSC_TRUE; 4653 inext = next->handlers; 4654 while (inext) { 4655 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4656 if (flg) { 4657 if (foundmtype) *foundmtype = PETSC_TRUE; 4658 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4659 PetscFunctionReturn(PETSC_SUCCESS); 4660 } 4661 inext = inext->next; 4662 } 4663 } 4664 next = next->next; 4665 } 4666 } else { 4667 while (next) { 4668 inext = next->handlers; 4669 while (inext) { 4670 PetscCall(PetscStrcmp(mtype, inext->mtype, &flg)); 4671 if (flg && inext->createfactor[(int)ftype - 1]) { 4672 if (foundtype) *foundtype = PETSC_TRUE; 4673 if (foundmtype) *foundmtype = PETSC_TRUE; 4674 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4675 PetscFunctionReturn(PETSC_SUCCESS); 4676 } 4677 inext = inext->next; 4678 } 4679 next = next->next; 4680 } 4681 /* try with base classes inext->mtype */ 4682 next = MatSolverTypeHolders; 4683 while (next) { 4684 inext = next->handlers; 4685 while (inext) { 4686 PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg)); 4687 if (flg && inext->createfactor[(int)ftype - 1]) { 4688 if (foundtype) *foundtype = PETSC_TRUE; 4689 if (foundmtype) *foundmtype = PETSC_TRUE; 4690 if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1]; 4691 PetscFunctionReturn(PETSC_SUCCESS); 4692 } 4693 inext = inext->next; 4694 } 4695 next = next->next; 4696 } 4697 } 4698 PetscFunctionReturn(PETSC_SUCCESS); 4699 } 4700 4701 PetscErrorCode MatSolverTypeDestroy(void) 4702 { 4703 MatSolverTypeHolder next = MatSolverTypeHolders, prev; 4704 MatSolverTypeForSpecifcType inext, iprev; 4705 4706 PetscFunctionBegin; 4707 while (next) { 4708 PetscCall(PetscFree(next->name)); 4709 inext = next->handlers; 4710 while (inext) { 4711 PetscCall(PetscFree(inext->mtype)); 4712 iprev = inext; 4713 inext = inext->next; 4714 PetscCall(PetscFree(iprev)); 4715 } 4716 prev = next; 4717 next = next->next; 4718 PetscCall(PetscFree(prev)); 4719 } 4720 MatSolverTypeHolders = NULL; 4721 PetscFunctionReturn(PETSC_SUCCESS); 4722 } 4723 4724 /*@ 4725 MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4726 4727 Logically Collective 4728 4729 Input Parameter: 4730 . mat - the matrix 4731 4732 Output Parameter: 4733 . flg - `PETSC_TRUE` if uses the ordering 4734 4735 Level: developer 4736 4737 Note: 4738 Most internal PETSc factorizations use the ordering passed to the factorization routine but external 4739 packages do not, thus we want to skip generating the ordering when it is not needed or used. 4740 4741 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4742 @*/ 4743 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) 4744 { 4745 PetscFunctionBegin; 4746 *flg = mat->canuseordering; 4747 PetscFunctionReturn(PETSC_SUCCESS); 4748 } 4749 4750 /*@ 4751 MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object 4752 4753 Logically Collective 4754 4755 Input Parameters: 4756 + mat - the matrix obtained with `MatGetFactor()` 4757 - ftype - the factorization type to be used 4758 4759 Output Parameter: 4760 . otype - the preferred ordering type 4761 4762 Level: developer 4763 4764 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()` 4765 @*/ 4766 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) 4767 { 4768 PetscFunctionBegin; 4769 *otype = mat->preferredordering[ftype]; 4770 PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering"); 4771 PetscFunctionReturn(PETSC_SUCCESS); 4772 } 4773 4774 /*@ 4775 MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric() 4776 4777 Collective 4778 4779 Input Parameters: 4780 + mat - the matrix 4781 . 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 4782 the other criteria is returned 4783 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4784 4785 Output Parameter: 4786 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below. 4787 4788 Options Database Keys: 4789 + -pc_factor_mat_solver_type <type> - choose the type at run time. When using `KSP` solvers 4790 . -pc_factor_mat_factor_on_host <bool> - do mat factorization on host (with device matrices). Default is doing it on device 4791 - -pc_factor_mat_solve_on_host <bool> - do mat solve on host (with device matrices). Default is doing it on device 4792 4793 Level: intermediate 4794 4795 Notes: 4796 The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization 4797 types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime. 4798 4799 Users usually access the factorization solvers via `KSP` 4800 4801 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4802 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 4803 4804 When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`. 4805 Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver. 4806 For example if one configuration had --download-mumps while a different one had --download-superlu_dist. 4807 4808 Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption 4809 where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set 4810 call `MatSetOptionsPrefixFactor()` on the originating matrix or `MatSetOptionsPrefix()` on the resulting factor matrix. 4811 4812 Developer Note: 4813 This should actually be called `MatCreateFactor()` since it creates a new factor object 4814 4815 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, 4816 `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()` 4817 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()` 4818 @*/ 4819 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) 4820 { 4821 PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE; 4822 PetscErrorCode (*conv)(Mat, MatFactorType, Mat *); 4823 4824 PetscFunctionBegin; 4825 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4826 PetscValidType(mat, 1); 4827 4828 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4829 MatCheckPreallocated(mat, 1); 4830 4831 PetscCall(MatIsShell(mat, &shell)); 4832 if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop)); 4833 if (hasop) { 4834 PetscUseTypeMethod(mat, getfactor, type, ftype, f); 4835 PetscFunctionReturn(PETSC_SUCCESS); 4836 } 4837 4838 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv)); 4839 if (!foundtype) { 4840 if (type) { 4841 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], 4842 ((PetscObject)mat)->type_name, type); 4843 } else { 4844 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); 4845 } 4846 } 4847 PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name); 4848 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); 4849 4850 PetscCall((*conv)(mat, ftype, f)); 4851 if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix)); 4852 PetscFunctionReturn(PETSC_SUCCESS); 4853 } 4854 4855 /*@ 4856 MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type 4857 4858 Not Collective 4859 4860 Input Parameters: 4861 + mat - the matrix 4862 . type - name of solver type, for example, `superlu`, `petsc` (to use PETSc's default) 4863 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR` 4864 4865 Output Parameter: 4866 . flg - PETSC_TRUE if the factorization is available 4867 4868 Level: intermediate 4869 4870 Notes: 4871 Some PETSc matrix formats have alternative solvers available that are contained in alternative packages 4872 such as pastix, superlu, mumps etc. 4873 4874 PETSc must have been ./configure to use the external solver, using the option --download-package 4875 4876 Developer Note: 4877 This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object 4878 4879 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`, 4880 `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()` 4881 @*/ 4882 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) 4883 { 4884 PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *); 4885 4886 PetscFunctionBegin; 4887 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4888 PetscAssertPointer(flg, 4); 4889 4890 *flg = PETSC_FALSE; 4891 if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS); 4892 4893 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4894 MatCheckPreallocated(mat, 1); 4895 4896 PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv)); 4897 *flg = gconv ? PETSC_TRUE : PETSC_FALSE; 4898 PetscFunctionReturn(PETSC_SUCCESS); 4899 } 4900 4901 /*@ 4902 MatDuplicate - Duplicates a matrix including the non-zero structure. 4903 4904 Collective 4905 4906 Input Parameters: 4907 + mat - the matrix 4908 - op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`. 4909 See the manual page for `MatDuplicateOption()` for an explanation of these options. 4910 4911 Output Parameter: 4912 . M - pointer to place new matrix 4913 4914 Level: intermediate 4915 4916 Notes: 4917 You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`. 4918 4919 If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed. 4920 4921 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. 4922 4923 When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat` 4924 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 4925 User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation. 4926 4927 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption` 4928 @*/ 4929 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) 4930 { 4931 Mat B; 4932 VecType vtype; 4933 PetscInt i; 4934 PetscObject dm, container_h, container_d; 4935 PetscErrorCodeFn *viewf; 4936 4937 PetscFunctionBegin; 4938 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 4939 PetscValidType(mat, 1); 4940 PetscAssertPointer(M, 3); 4941 PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix"); 4942 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 4943 MatCheckPreallocated(mat, 1); 4944 4945 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4946 PetscUseTypeMethod(mat, duplicate, op, M); 4947 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4948 B = *M; 4949 4950 PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf)); 4951 if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf)); 4952 PetscCall(MatGetVecType(mat, &vtype)); 4953 PetscCall(MatSetVecType(B, vtype)); 4954 4955 B->stencil.dim = mat->stencil.dim; 4956 B->stencil.noc = mat->stencil.noc; 4957 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4958 B->stencil.dims[i] = mat->stencil.dims[i]; 4959 B->stencil.starts[i] = mat->stencil.starts[i]; 4960 } 4961 4962 B->nooffproczerorows = mat->nooffproczerorows; 4963 B->nooffprocentries = mat->nooffprocentries; 4964 4965 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm)); 4966 if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm)); 4967 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h)); 4968 if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h)); 4969 PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d)); 4970 if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d)); 4971 if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B)); 4972 PetscCall(PetscObjectStateIncrease((PetscObject)B)); 4973 PetscFunctionReturn(PETSC_SUCCESS); 4974 } 4975 4976 /*@ 4977 MatGetDiagonal - Gets the diagonal of a matrix as a `Vec` 4978 4979 Logically Collective 4980 4981 Input Parameter: 4982 . mat - the matrix 4983 4984 Output Parameter: 4985 . v - the diagonal of the matrix 4986 4987 Level: intermediate 4988 4989 Note: 4990 If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries 4991 of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v` 4992 is larger than `ndiag`, the values of the remaining entries are unspecified. 4993 4994 Currently only correct in parallel for square matrices. 4995 4996 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()` 4997 @*/ 4998 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) 4999 { 5000 PetscFunctionBegin; 5001 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5002 PetscValidType(mat, 1); 5003 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5004 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5005 MatCheckPreallocated(mat, 1); 5006 if (PetscDefined(USE_DEBUG)) { 5007 PetscInt nv, row, col, ndiag; 5008 5009 PetscCall(VecGetLocalSize(v, &nv)); 5010 PetscCall(MatGetLocalSize(mat, &row, &col)); 5011 ndiag = PetscMin(row, col); 5012 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); 5013 } 5014 5015 PetscUseTypeMethod(mat, getdiagonal, v); 5016 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5017 PetscFunctionReturn(PETSC_SUCCESS); 5018 } 5019 5020 /*@ 5021 MatGetRowMin - Gets the minimum value (of the real part) of each 5022 row of the matrix 5023 5024 Logically Collective 5025 5026 Input Parameter: 5027 . mat - the matrix 5028 5029 Output Parameters: 5030 + v - the vector for storing the maximums 5031 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed) 5032 5033 Level: intermediate 5034 5035 Note: 5036 The result of this call are the same as if one converted the matrix to dense format 5037 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5038 5039 This code is only implemented for a couple of matrix formats. 5040 5041 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, 5042 `MatGetRowMax()` 5043 @*/ 5044 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) 5045 { 5046 PetscFunctionBegin; 5047 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5048 PetscValidType(mat, 1); 5049 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5050 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5051 5052 if (!mat->cmap->N) { 5053 PetscCall(VecSet(v, PETSC_MAX_REAL)); 5054 if (idx) { 5055 PetscInt i, m = mat->rmap->n; 5056 for (i = 0; i < m; i++) idx[i] = -1; 5057 } 5058 } else { 5059 MatCheckPreallocated(mat, 1); 5060 } 5061 PetscUseTypeMethod(mat, getrowmin, v, idx); 5062 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5063 PetscFunctionReturn(PETSC_SUCCESS); 5064 } 5065 5066 /*@ 5067 MatGetRowMinAbs - Gets the minimum value (in absolute value) of each 5068 row of the matrix 5069 5070 Logically Collective 5071 5072 Input Parameter: 5073 . mat - the matrix 5074 5075 Output Parameters: 5076 + v - the vector for storing the minimums 5077 - idx - the indices of the column found for each row (or `NULL` if not needed) 5078 5079 Level: intermediate 5080 5081 Notes: 5082 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5083 row is 0 (the first column). 5084 5085 This code is only implemented for a couple of matrix formats. 5086 5087 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()` 5088 @*/ 5089 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) 5090 { 5091 PetscFunctionBegin; 5092 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5093 PetscValidType(mat, 1); 5094 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5095 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5096 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5097 5098 if (!mat->cmap->N) { 5099 PetscCall(VecSet(v, 0.0)); 5100 if (idx) { 5101 PetscInt i, m = mat->rmap->n; 5102 for (i = 0; i < m; i++) idx[i] = -1; 5103 } 5104 } else { 5105 MatCheckPreallocated(mat, 1); 5106 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5107 PetscUseTypeMethod(mat, getrowminabs, v, idx); 5108 } 5109 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5110 PetscFunctionReturn(PETSC_SUCCESS); 5111 } 5112 5113 /*@ 5114 MatGetRowMax - Gets the maximum value (of the real part) of each 5115 row of the matrix 5116 5117 Logically Collective 5118 5119 Input Parameter: 5120 . mat - the matrix 5121 5122 Output Parameters: 5123 + v - the vector for storing the maximums 5124 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`) 5125 5126 Level: intermediate 5127 5128 Notes: 5129 The result of this call are the same as if one converted the matrix to dense format 5130 and found the minimum value in each row (i.e. the implicit zeros are counted as zeros). 5131 5132 This code is only implemented for a couple of matrix formats. 5133 5134 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5135 @*/ 5136 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) 5137 { 5138 PetscFunctionBegin; 5139 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5140 PetscValidType(mat, 1); 5141 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5142 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5143 5144 if (!mat->cmap->N) { 5145 PetscCall(VecSet(v, PETSC_MIN_REAL)); 5146 if (idx) { 5147 PetscInt i, m = mat->rmap->n; 5148 for (i = 0; i < m; i++) idx[i] = -1; 5149 } 5150 } else { 5151 MatCheckPreallocated(mat, 1); 5152 PetscUseTypeMethod(mat, getrowmax, v, idx); 5153 } 5154 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5155 PetscFunctionReturn(PETSC_SUCCESS); 5156 } 5157 5158 /*@ 5159 MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each 5160 row of the matrix 5161 5162 Logically Collective 5163 5164 Input Parameter: 5165 . mat - the matrix 5166 5167 Output Parameters: 5168 + v - the vector for storing the maximums 5169 - idx - the indices of the column found for each row (or `NULL` if not needed) 5170 5171 Level: intermediate 5172 5173 Notes: 5174 if a row is completely empty or has only 0.0 values, then the `idx` value for that 5175 row is 0 (the first column). 5176 5177 This code is only implemented for a couple of matrix formats. 5178 5179 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5180 @*/ 5181 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) 5182 { 5183 PetscFunctionBegin; 5184 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5185 PetscValidType(mat, 1); 5186 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5187 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5188 5189 if (!mat->cmap->N) { 5190 PetscCall(VecSet(v, 0.0)); 5191 if (idx) { 5192 PetscInt i, m = mat->rmap->n; 5193 for (i = 0; i < m; i++) idx[i] = -1; 5194 } 5195 } else { 5196 MatCheckPreallocated(mat, 1); 5197 if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n)); 5198 PetscUseTypeMethod(mat, getrowmaxabs, v, idx); 5199 } 5200 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5201 PetscFunctionReturn(PETSC_SUCCESS); 5202 } 5203 5204 /*@ 5205 MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix 5206 5207 Logically Collective 5208 5209 Input Parameter: 5210 . mat - the matrix 5211 5212 Output Parameter: 5213 . v - the vector for storing the sum 5214 5215 Level: intermediate 5216 5217 This code is only implemented for a couple of matrix formats. 5218 5219 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()` 5220 @*/ 5221 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v) 5222 { 5223 PetscFunctionBegin; 5224 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5225 PetscValidType(mat, 1); 5226 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5227 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5228 5229 if (!mat->cmap->N) { 5230 PetscCall(VecSet(v, 0.0)); 5231 } else { 5232 MatCheckPreallocated(mat, 1); 5233 PetscUseTypeMethod(mat, getrowsumabs, v); 5234 } 5235 PetscCall(PetscObjectStateIncrease((PetscObject)v)); 5236 PetscFunctionReturn(PETSC_SUCCESS); 5237 } 5238 5239 /*@ 5240 MatGetRowSum - Gets the sum of each row of the matrix 5241 5242 Logically or Neighborhood Collective 5243 5244 Input Parameter: 5245 . mat - the matrix 5246 5247 Output Parameter: 5248 . v - the vector for storing the sum of rows 5249 5250 Level: intermediate 5251 5252 Note: 5253 This code is slow since it is not currently specialized for different formats 5254 5255 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()` 5256 @*/ 5257 PetscErrorCode MatGetRowSum(Mat mat, Vec v) 5258 { 5259 Vec ones; 5260 5261 PetscFunctionBegin; 5262 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5263 PetscValidType(mat, 1); 5264 PetscValidHeaderSpecific(v, VEC_CLASSID, 2); 5265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5266 MatCheckPreallocated(mat, 1); 5267 PetscCall(MatCreateVecs(mat, &ones, NULL)); 5268 PetscCall(VecSet(ones, 1.)); 5269 PetscCall(MatMult(mat, ones, v)); 5270 PetscCall(VecDestroy(&ones)); 5271 PetscFunctionReturn(PETSC_SUCCESS); 5272 } 5273 5274 /*@ 5275 MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) 5276 when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B) 5277 5278 Collective 5279 5280 Input Parameter: 5281 . mat - the matrix to provide the transpose 5282 5283 Output Parameter: 5284 . 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 5285 5286 Level: advanced 5287 5288 Note: 5289 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 5290 routine allows bypassing that call. 5291 5292 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5293 @*/ 5294 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) 5295 { 5296 MatParentState *rb = NULL; 5297 5298 PetscFunctionBegin; 5299 PetscCall(PetscNew(&rb)); 5300 rb->id = ((PetscObject)mat)->id; 5301 rb->state = 0; 5302 PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate)); 5303 PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscCtxDestroyDefault)); 5304 PetscFunctionReturn(PETSC_SUCCESS); 5305 } 5306 5307 /*@ 5308 MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place. 5309 5310 Collective 5311 5312 Input Parameters: 5313 + mat - the matrix to transpose 5314 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5315 5316 Output Parameter: 5317 . B - the transpose of the matrix 5318 5319 Level: intermediate 5320 5321 Notes: 5322 If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B` 5323 5324 `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 5325 transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine. 5326 5327 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. 5328 5329 Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed. 5330 For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`. 5331 5332 If `mat` is unchanged from the last call this function returns immediately without recomputing the result 5333 5334 If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()` 5335 5336 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`, 5337 `MatTransposeSymbolic()`, `MatCreateTranspose()` 5338 @*/ 5339 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) 5340 { 5341 PetscContainer rB = NULL; 5342 MatParentState *rb = NULL; 5343 5344 PetscFunctionBegin; 5345 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5346 PetscValidType(mat, 1); 5347 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5348 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5349 PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first"); 5350 PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX"); 5351 MatCheckPreallocated(mat, 1); 5352 if (reuse == MAT_REUSE_MATRIX) { 5353 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5354 PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor()."); 5355 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5356 PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5357 if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS); 5358 } 5359 5360 PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0)); 5361 if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) { 5362 PetscUseTypeMethod(mat, transpose, reuse, B); 5363 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5364 } 5365 PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0)); 5366 5367 if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B)); 5368 if (reuse != MAT_INPLACE_MATRIX) { 5369 PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB)); 5370 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5371 rb->state = ((PetscObject)mat)->state; 5372 rb->nonzerostate = mat->nonzerostate; 5373 } 5374 PetscFunctionReturn(PETSC_SUCCESS); 5375 } 5376 5377 /*@ 5378 MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix. 5379 5380 Collective 5381 5382 Input Parameter: 5383 . A - the matrix to transpose 5384 5385 Output Parameter: 5386 . 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 5387 numerical portion. 5388 5389 Level: intermediate 5390 5391 Note: 5392 This is not supported for many matrix types, use `MatTranspose()` in those cases 5393 5394 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX` 5395 @*/ 5396 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) 5397 { 5398 PetscFunctionBegin; 5399 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5400 PetscValidType(A, 1); 5401 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5402 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5403 PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0)); 5404 PetscUseTypeMethod(A, transposesymbolic, B); 5405 PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0)); 5406 5407 PetscCall(MatTransposeSetPrecursor(A, *B)); 5408 PetscFunctionReturn(PETSC_SUCCESS); 5409 } 5410 5411 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) 5412 { 5413 PetscContainer rB; 5414 MatParentState *rb; 5415 5416 PetscFunctionBegin; 5417 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5418 PetscValidType(A, 1); 5419 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5420 PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5421 PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB)); 5422 PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()"); 5423 PetscCall(PetscContainerGetPointer(rB, (void **)&rb)); 5424 PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix"); 5425 PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure"); 5426 PetscFunctionReturn(PETSC_SUCCESS); 5427 } 5428 5429 /*@ 5430 MatIsTranspose - Test whether a matrix is another one's transpose, 5431 or its own, in which case it tests symmetry. 5432 5433 Collective 5434 5435 Input Parameters: 5436 + A - the matrix to test 5437 . B - the matrix to test against, this can equal the first parameter 5438 - tol - tolerance, differences between entries smaller than this are counted as zero 5439 5440 Output Parameter: 5441 . flg - the result 5442 5443 Level: intermediate 5444 5445 Notes: 5446 The sequential algorithm has a running time of the order of the number of nonzeros; the parallel 5447 test involves parallel copies of the block off-diagonal parts of the matrix. 5448 5449 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()` 5450 @*/ 5451 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5452 { 5453 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5454 5455 PetscFunctionBegin; 5456 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5457 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5458 PetscAssertPointer(flg, 4); 5459 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f)); 5460 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g)); 5461 *flg = PETSC_FALSE; 5462 if (f && g) { 5463 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test"); 5464 PetscCall((*f)(A, B, tol, flg)); 5465 } else { 5466 MatType mattype; 5467 5468 PetscCall(MatGetType(f ? B : A, &mattype)); 5469 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype); 5470 } 5471 PetscFunctionReturn(PETSC_SUCCESS); 5472 } 5473 5474 /*@ 5475 MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate. 5476 5477 Collective 5478 5479 Input Parameters: 5480 + mat - the matrix to transpose and complex conjugate 5481 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX` 5482 5483 Output Parameter: 5484 . B - the Hermitian transpose 5485 5486 Level: intermediate 5487 5488 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse` 5489 @*/ 5490 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) 5491 { 5492 PetscFunctionBegin; 5493 PetscCall(MatTranspose(mat, reuse, B)); 5494 #if defined(PETSC_USE_COMPLEX) 5495 PetscCall(MatConjugate(*B)); 5496 #endif 5497 PetscFunctionReturn(PETSC_SUCCESS); 5498 } 5499 5500 /*@ 5501 MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose, 5502 5503 Collective 5504 5505 Input Parameters: 5506 + A - the matrix to test 5507 . B - the matrix to test against, this can equal the first parameter 5508 - tol - tolerance, differences between entries smaller than this are counted as zero 5509 5510 Output Parameter: 5511 . flg - the result 5512 5513 Level: intermediate 5514 5515 Notes: 5516 Only available for `MATAIJ` matrices. 5517 5518 The sequential algorithm 5519 has a running time of the order of the number of nonzeros; the parallel 5520 test involves parallel copies of the block off-diagonal parts of the matrix. 5521 5522 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()` 5523 @*/ 5524 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) 5525 { 5526 PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *); 5527 5528 PetscFunctionBegin; 5529 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5530 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5531 PetscAssertPointer(flg, 4); 5532 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f)); 5533 PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g)); 5534 if (f && g) { 5535 PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test"); 5536 PetscCall((*f)(A, B, tol, flg)); 5537 } else { 5538 MatType mattype; 5539 5540 PetscCall(MatGetType(f ? B : A, &mattype)); 5541 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for Hermitian transpose", mattype); 5542 } 5543 PetscFunctionReturn(PETSC_SUCCESS); 5544 } 5545 5546 /*@ 5547 MatPermute - Creates a new matrix with rows and columns permuted from the 5548 original. 5549 5550 Collective 5551 5552 Input Parameters: 5553 + mat - the matrix to permute 5554 . row - row permutation, each processor supplies only the permutation for its rows 5555 - col - column permutation, each processor supplies only the permutation for its columns 5556 5557 Output Parameter: 5558 . B - the permuted matrix 5559 5560 Level: advanced 5561 5562 Note: 5563 The index sets map from row/col of permuted matrix to row/col of original matrix. 5564 The index sets should be on the same communicator as mat and have the same local sizes. 5565 5566 Developer Note: 5567 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5568 exploit the fact that row and col are permutations, consider implementing the 5569 more general `MatCreateSubMatrix()` instead. 5570 5571 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5572 @*/ 5573 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5574 { 5575 PetscFunctionBegin; 5576 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5577 PetscValidType(mat, 1); 5578 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5579 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5580 PetscAssertPointer(B, 4); 5581 PetscCheckSameComm(mat, 1, row, 2); 5582 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5583 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5584 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5585 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5586 MatCheckPreallocated(mat, 1); 5587 5588 if (mat->ops->permute) { 5589 PetscUseTypeMethod(mat, permute, row, col, B); 5590 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5591 } else { 5592 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5593 } 5594 PetscFunctionReturn(PETSC_SUCCESS); 5595 } 5596 5597 /*@ 5598 MatEqual - Compares two matrices. 5599 5600 Collective 5601 5602 Input Parameters: 5603 + A - the first matrix 5604 - B - the second matrix 5605 5606 Output Parameter: 5607 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5608 5609 Level: intermediate 5610 5611 Note: 5612 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing 5613 the results of several matrix-vector product using randomly created vectors, see `MatMultEqual()`. 5614 5615 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5616 @*/ 5617 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5618 { 5619 PetscFunctionBegin; 5620 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5621 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5622 PetscValidType(A, 1); 5623 PetscValidType(B, 2); 5624 PetscAssertPointer(flg, 3); 5625 PetscCheckSameComm(A, 1, B, 2); 5626 MatCheckPreallocated(A, 1); 5627 MatCheckPreallocated(B, 2); 5628 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5629 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5630 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, 5631 B->cmap->N); 5632 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5633 PetscUseTypeMethod(A, equal, B, flg); 5634 } else { 5635 PetscCall(MatMultEqual(A, B, 10, flg)); 5636 } 5637 PetscFunctionReturn(PETSC_SUCCESS); 5638 } 5639 5640 /*@ 5641 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5642 matrices that are stored as vectors. Either of the two scaling 5643 matrices can be `NULL`. 5644 5645 Collective 5646 5647 Input Parameters: 5648 + mat - the matrix to be scaled 5649 . l - the left scaling vector (or `NULL`) 5650 - r - the right scaling vector (or `NULL`) 5651 5652 Level: intermediate 5653 5654 Note: 5655 `MatDiagonalScale()` computes $A = LAR$, where 5656 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5657 The L scales the rows of the matrix, the R scales the columns of the matrix. 5658 5659 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5660 @*/ 5661 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5662 { 5663 PetscBool flg = PETSC_FALSE; 5664 5665 PetscFunctionBegin; 5666 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5667 PetscValidType(mat, 1); 5668 if (l) { 5669 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5670 PetscCheckSameComm(mat, 1, l, 2); 5671 } 5672 if (r) { 5673 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5674 PetscCheckSameComm(mat, 1, r, 3); 5675 } 5676 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5677 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5678 MatCheckPreallocated(mat, 1); 5679 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5680 5681 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5682 PetscUseTypeMethod(mat, diagonalscale, l, r); 5683 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5684 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5685 if (l != r && (PetscBool3ToBool(mat->symmetric) || PetscBool3ToBool(mat->hermitian))) { 5686 if (!PetscDefined(USE_COMPLEX) || PetscBool3ToBool(mat->symmetric)) { 5687 if (l && r) PetscCall(VecEqual(l, r, &flg)); 5688 if (!flg) { 5689 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &flg, MATSEQSBAIJ, MATMPISBAIJ, "")); 5690 PetscCheck(!flg, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "For symmetric format, left and right scaling vectors must be the same"); 5691 mat->symmetric = mat->spd = PETSC_BOOL3_FALSE; 5692 if (!PetscDefined(USE_COMPLEX)) mat->hermitian = PETSC_BOOL3_FALSE; 5693 else mat->hermitian = PETSC_BOOL3_UNKNOWN; 5694 } 5695 } 5696 if (PetscDefined(USE_COMPLEX) && PetscBool3ToBool(mat->hermitian)) { 5697 flg = PETSC_FALSE; 5698 if (l && r) { 5699 Vec conjugate; 5700 5701 PetscCall(VecDuplicate(l, &conjugate)); 5702 PetscCall(VecCopy(l, conjugate)); 5703 PetscCall(VecConjugate(conjugate)); 5704 PetscCall(VecEqual(conjugate, r, &flg)); 5705 PetscCall(VecDestroy(&conjugate)); 5706 } 5707 if (!flg) { 5708 PetscCall(PetscObjectTypeCompareAny((PetscObject)mat, &flg, MATSEQSBAIJ, MATMPISBAIJ, "")); 5709 PetscCheck(!flg, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "For symmetric format and Hermitian matrix, left and right scaling vectors must be conjugate one of the other"); 5710 mat->hermitian = PETSC_BOOL3_FALSE; 5711 mat->symmetric = mat->spd = PETSC_BOOL3_UNKNOWN; 5712 } 5713 } 5714 } 5715 PetscFunctionReturn(PETSC_SUCCESS); 5716 } 5717 5718 /*@ 5719 MatScale - Scales all elements of a matrix by a given number. 5720 5721 Logically Collective 5722 5723 Input Parameters: 5724 + mat - the matrix to be scaled 5725 - a - the scaling value 5726 5727 Level: intermediate 5728 5729 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5730 @*/ 5731 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5732 { 5733 PetscFunctionBegin; 5734 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5735 PetscValidType(mat, 1); 5736 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5737 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5738 PetscValidLogicalCollectiveScalar(mat, a, 2); 5739 MatCheckPreallocated(mat, 1); 5740 5741 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5742 if (a != (PetscScalar)1.0) { 5743 PetscUseTypeMethod(mat, scale, a); 5744 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5745 } 5746 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5747 PetscFunctionReturn(PETSC_SUCCESS); 5748 } 5749 5750 /*@ 5751 MatNorm - Calculates various norms of a matrix. 5752 5753 Collective 5754 5755 Input Parameters: 5756 + mat - the matrix 5757 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5758 5759 Output Parameter: 5760 . nrm - the resulting norm 5761 5762 Level: intermediate 5763 5764 .seealso: [](ch_matrices), `Mat` 5765 @*/ 5766 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5767 { 5768 PetscFunctionBegin; 5769 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5770 PetscValidType(mat, 1); 5771 PetscAssertPointer(nrm, 3); 5772 5773 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5774 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5775 MatCheckPreallocated(mat, 1); 5776 5777 PetscUseTypeMethod(mat, norm, type, nrm); 5778 PetscFunctionReturn(PETSC_SUCCESS); 5779 } 5780 5781 /* 5782 This variable is used to prevent counting of MatAssemblyBegin() that 5783 are called from within a MatAssemblyEnd(). 5784 */ 5785 static PetscInt MatAssemblyEnd_InUse = 0; 5786 /*@ 5787 MatAssemblyBegin - Begins assembling the matrix. This routine should 5788 be called after completing all calls to `MatSetValues()`. 5789 5790 Collective 5791 5792 Input Parameters: 5793 + mat - the matrix 5794 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5795 5796 Level: beginner 5797 5798 Notes: 5799 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5800 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5801 5802 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5803 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5804 using the matrix. 5805 5806 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5807 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 5808 a global collective operation requiring all processes that share the matrix. 5809 5810 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5811 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5812 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5813 5814 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5815 @*/ 5816 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5817 { 5818 PetscFunctionBegin; 5819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5820 PetscValidType(mat, 1); 5821 MatCheckPreallocated(mat, 1); 5822 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5823 if (mat->assembled) { 5824 mat->was_assembled = PETSC_TRUE; 5825 mat->assembled = PETSC_FALSE; 5826 } 5827 5828 if (!MatAssemblyEnd_InUse) { 5829 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5830 PetscTryTypeMethod(mat, assemblybegin, type); 5831 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5832 } else PetscTryTypeMethod(mat, assemblybegin, type); 5833 PetscFunctionReturn(PETSC_SUCCESS); 5834 } 5835 5836 /*@ 5837 MatAssembled - Indicates if a matrix has been assembled and is ready for 5838 use; for example, in matrix-vector product. 5839 5840 Not Collective 5841 5842 Input Parameter: 5843 . mat - the matrix 5844 5845 Output Parameter: 5846 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5847 5848 Level: advanced 5849 5850 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5851 @*/ 5852 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5853 { 5854 PetscFunctionBegin; 5855 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5856 PetscAssertPointer(assembled, 2); 5857 *assembled = mat->assembled; 5858 PetscFunctionReturn(PETSC_SUCCESS); 5859 } 5860 5861 /*@ 5862 MatAssemblyEnd - Completes assembling the matrix. This routine should 5863 be called after `MatAssemblyBegin()`. 5864 5865 Collective 5866 5867 Input Parameters: 5868 + mat - the matrix 5869 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5870 5871 Options Database Keys: 5872 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5873 . -mat_view ::ascii_info_detail - Prints more detailed info 5874 . -mat_view - Prints matrix in ASCII format 5875 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5876 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5877 . -display <name> - Sets display name (default is host) 5878 . -draw_pause <sec> - Sets number of seconds to pause after display 5879 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5880 . -viewer_socket_machine <machine> - Machine to use for socket 5881 . -viewer_socket_port <port> - Port number to use for socket 5882 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5883 5884 Level: beginner 5885 5886 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5887 @*/ 5888 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5889 { 5890 static PetscInt inassm = 0; 5891 PetscBool flg = PETSC_FALSE; 5892 5893 PetscFunctionBegin; 5894 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5895 PetscValidType(mat, 1); 5896 5897 inassm++; 5898 MatAssemblyEnd_InUse++; 5899 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5900 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5901 PetscTryTypeMethod(mat, assemblyend, type); 5902 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5903 } else PetscTryTypeMethod(mat, assemblyend, type); 5904 5905 /* Flush assembly is not a true assembly */ 5906 if (type != MAT_FLUSH_ASSEMBLY) { 5907 if (mat->num_ass) { 5908 if (!mat->symmetry_eternal) { 5909 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5910 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5911 } 5912 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5913 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5914 } 5915 mat->num_ass++; 5916 mat->assembled = PETSC_TRUE; 5917 mat->ass_nonzerostate = mat->nonzerostate; 5918 } 5919 5920 mat->insertmode = NOT_SET_VALUES; 5921 MatAssemblyEnd_InUse--; 5922 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5923 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5924 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5925 5926 if (mat->checksymmetryonassembly) { 5927 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5928 if (flg) { 5929 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5930 } else { 5931 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5932 } 5933 } 5934 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5935 } 5936 inassm--; 5937 PetscFunctionReturn(PETSC_SUCCESS); 5938 } 5939 5940 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5941 /*@ 5942 MatSetOption - Sets a parameter option for a matrix. Some options 5943 may be specific to certain storage formats. Some options 5944 determine how values will be inserted (or added). Sorted, 5945 row-oriented input will generally assemble the fastest. The default 5946 is row-oriented. 5947 5948 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5949 5950 Input Parameters: 5951 + mat - the matrix 5952 . op - the option, one of those listed below (and possibly others), 5953 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5954 5955 Options Describing Matrix Structure: 5956 + `MAT_SPD` - symmetric positive definite 5957 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5958 . `MAT_HERMITIAN` - transpose is the complex conjugation 5959 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5960 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5961 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5962 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5963 5964 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5965 do not need to be computed (usually at a high cost) 5966 5967 Options For Use with `MatSetValues()`: 5968 Insert a logically dense subblock, which can be 5969 . `MAT_ROW_ORIENTED` - row-oriented (default) 5970 5971 These options reflect the data you pass in with `MatSetValues()`; it has 5972 nothing to do with how the data is stored internally in the matrix 5973 data structure. 5974 5975 When (re)assembling a matrix, we can restrict the input for 5976 efficiency/debugging purposes. These options include 5977 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5978 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5979 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5980 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5981 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5982 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5983 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5984 performance for very large process counts. 5985 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5986 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5987 functions, instead sending only neighbor messages. 5988 5989 Level: intermediate 5990 5991 Notes: 5992 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5993 5994 Some options are relevant only for particular matrix types and 5995 are thus ignored by others. Other options are not supported by 5996 certain matrix types and will generate an error message if set. 5997 5998 If using Fortran to compute a matrix, one may need to 5999 use the column-oriented option (or convert to the row-oriented 6000 format). 6001 6002 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 6003 that would generate a new entry in the nonzero structure is instead 6004 ignored. Thus, if memory has not already been allocated for this particular 6005 data, then the insertion is ignored. For dense matrices, in which 6006 the entire array is allocated, no entries are ever ignored. 6007 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6008 6009 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 6010 that would generate a new entry in the nonzero structure instead produces 6011 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 6012 6013 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 6014 that would generate a new entry that has not been preallocated will 6015 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 6016 only.) This is a useful flag when debugging matrix memory preallocation. 6017 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 6018 6019 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 6020 other processors should be dropped, rather than stashed. 6021 This is useful if you know that the "owning" processor is also 6022 always generating the correct matrix entries, so that PETSc need 6023 not transfer duplicate entries generated on another processor. 6024 6025 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 6026 searches during matrix assembly. When this flag is set, the hash table 6027 is created during the first matrix assembly. This hash table is 6028 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 6029 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 6030 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 6031 supported by `MATMPIBAIJ` format only. 6032 6033 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 6034 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 6035 6036 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6037 a zero location in the matrix 6038 6039 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6040 6041 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6042 zero row routines and thus improves performance for very large process counts. 6043 6044 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6045 part of the matrix (since they should match the upper triangular part). 6046 6047 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6048 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6049 with finite difference schemes with non-periodic boundary conditions. 6050 6051 Developer Note: 6052 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6053 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6054 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6055 not changed. 6056 6057 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6058 @*/ 6059 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6060 { 6061 PetscFunctionBegin; 6062 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6063 if (op > 0) { 6064 PetscValidLogicalCollectiveEnum(mat, op, 2); 6065 PetscValidLogicalCollectiveBool(mat, flg, 3); 6066 } 6067 6068 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); 6069 6070 switch (op) { 6071 case MAT_FORCE_DIAGONAL_ENTRIES: 6072 mat->force_diagonals = flg; 6073 PetscFunctionReturn(PETSC_SUCCESS); 6074 case MAT_NO_OFF_PROC_ENTRIES: 6075 mat->nooffprocentries = flg; 6076 PetscFunctionReturn(PETSC_SUCCESS); 6077 case MAT_SUBSET_OFF_PROC_ENTRIES: 6078 mat->assembly_subset = flg; 6079 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6080 #if !defined(PETSC_HAVE_MPIUNI) 6081 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6082 #endif 6083 mat->stash.first_assembly_done = PETSC_FALSE; 6084 } 6085 PetscFunctionReturn(PETSC_SUCCESS); 6086 case MAT_NO_OFF_PROC_ZERO_ROWS: 6087 mat->nooffproczerorows = flg; 6088 PetscFunctionReturn(PETSC_SUCCESS); 6089 case MAT_SPD: 6090 if (flg) { 6091 mat->spd = PETSC_BOOL3_TRUE; 6092 mat->symmetric = PETSC_BOOL3_TRUE; 6093 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6094 #if !defined(PETSC_USE_COMPLEX) 6095 mat->hermitian = PETSC_BOOL3_TRUE; 6096 #endif 6097 } else { 6098 mat->spd = PETSC_BOOL3_FALSE; 6099 } 6100 break; 6101 case MAT_SYMMETRIC: 6102 mat->symmetric = PetscBoolToBool3(flg); 6103 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6104 #if !defined(PETSC_USE_COMPLEX) 6105 mat->hermitian = PetscBoolToBool3(flg); 6106 #endif 6107 break; 6108 case MAT_HERMITIAN: 6109 mat->hermitian = PetscBoolToBool3(flg); 6110 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6111 #if !defined(PETSC_USE_COMPLEX) 6112 mat->symmetric = PetscBoolToBool3(flg); 6113 #endif 6114 break; 6115 case MAT_STRUCTURALLY_SYMMETRIC: 6116 mat->structurally_symmetric = PetscBoolToBool3(flg); 6117 break; 6118 case MAT_SYMMETRY_ETERNAL: 6119 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"); 6120 mat->symmetry_eternal = flg; 6121 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6122 break; 6123 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6124 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"); 6125 mat->structural_symmetry_eternal = flg; 6126 break; 6127 case MAT_SPD_ETERNAL: 6128 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"); 6129 mat->spd_eternal = flg; 6130 if (flg) { 6131 mat->structural_symmetry_eternal = PETSC_TRUE; 6132 mat->symmetry_eternal = PETSC_TRUE; 6133 } 6134 break; 6135 case MAT_STRUCTURE_ONLY: 6136 mat->structure_only = flg; 6137 break; 6138 case MAT_SORTED_FULL: 6139 mat->sortedfull = flg; 6140 break; 6141 default: 6142 break; 6143 } 6144 PetscTryTypeMethod(mat, setoption, op, flg); 6145 PetscFunctionReturn(PETSC_SUCCESS); 6146 } 6147 6148 /*@ 6149 MatGetOption - Gets a parameter option that has been set for a matrix. 6150 6151 Logically Collective 6152 6153 Input Parameters: 6154 + mat - the matrix 6155 - op - the option, this only responds to certain options, check the code for which ones 6156 6157 Output Parameter: 6158 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6159 6160 Level: intermediate 6161 6162 Notes: 6163 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6164 6165 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6166 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6167 6168 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6169 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6170 @*/ 6171 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6172 { 6173 PetscFunctionBegin; 6174 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6175 PetscValidType(mat, 1); 6176 6177 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); 6178 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()"); 6179 6180 switch (op) { 6181 case MAT_NO_OFF_PROC_ENTRIES: 6182 *flg = mat->nooffprocentries; 6183 break; 6184 case MAT_NO_OFF_PROC_ZERO_ROWS: 6185 *flg = mat->nooffproczerorows; 6186 break; 6187 case MAT_SYMMETRIC: 6188 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6189 break; 6190 case MAT_HERMITIAN: 6191 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6192 break; 6193 case MAT_STRUCTURALLY_SYMMETRIC: 6194 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6195 break; 6196 case MAT_SPD: 6197 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6198 break; 6199 case MAT_SYMMETRY_ETERNAL: 6200 *flg = mat->symmetry_eternal; 6201 break; 6202 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6203 *flg = mat->symmetry_eternal; 6204 break; 6205 default: 6206 break; 6207 } 6208 PetscFunctionReturn(PETSC_SUCCESS); 6209 } 6210 6211 /*@ 6212 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6213 this routine retains the old nonzero structure. 6214 6215 Logically Collective 6216 6217 Input Parameter: 6218 . mat - the matrix 6219 6220 Level: intermediate 6221 6222 Note: 6223 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. 6224 See the Performance chapter of the users manual for information on preallocating matrices. 6225 6226 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6227 @*/ 6228 PetscErrorCode MatZeroEntries(Mat mat) 6229 { 6230 PetscFunctionBegin; 6231 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6232 PetscValidType(mat, 1); 6233 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6234 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"); 6235 MatCheckPreallocated(mat, 1); 6236 6237 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6238 PetscUseTypeMethod(mat, zeroentries); 6239 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6240 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6241 PetscFunctionReturn(PETSC_SUCCESS); 6242 } 6243 6244 /*@ 6245 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6246 of a set of rows and columns of a matrix. 6247 6248 Collective 6249 6250 Input Parameters: 6251 + mat - the matrix 6252 . numRows - the number of rows/columns to zero 6253 . rows - the global row indices 6254 . diag - value put in the diagonal of the eliminated rows 6255 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6256 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6257 6258 Level: intermediate 6259 6260 Notes: 6261 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6262 6263 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6264 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 6265 6266 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6267 Krylov method to take advantage of the known solution on the zeroed rows. 6268 6269 For the parallel case, all processes that share the matrix (i.e., 6270 those in the communicator used for matrix creation) MUST call this 6271 routine, regardless of whether any rows being zeroed are owned by 6272 them. 6273 6274 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6275 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 6276 missing. 6277 6278 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6279 list only rows local to itself). 6280 6281 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6282 6283 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6284 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6285 @*/ 6286 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6287 { 6288 PetscFunctionBegin; 6289 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6290 PetscValidType(mat, 1); 6291 if (numRows) PetscAssertPointer(rows, 3); 6292 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6293 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6294 MatCheckPreallocated(mat, 1); 6295 6296 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6297 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6298 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6299 PetscFunctionReturn(PETSC_SUCCESS); 6300 } 6301 6302 /*@ 6303 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6304 of a set of rows and columns of a matrix. 6305 6306 Collective 6307 6308 Input Parameters: 6309 + mat - the matrix 6310 . is - the rows to zero 6311 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6312 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6313 - b - optional vector of right-hand side, that will be adjusted by provided solution 6314 6315 Level: intermediate 6316 6317 Note: 6318 See `MatZeroRowsColumns()` for details on how this routine operates. 6319 6320 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6321 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6322 @*/ 6323 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6324 { 6325 PetscInt numRows; 6326 const PetscInt *rows; 6327 6328 PetscFunctionBegin; 6329 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6330 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6331 PetscValidType(mat, 1); 6332 PetscValidType(is, 2); 6333 PetscCall(ISGetLocalSize(is, &numRows)); 6334 PetscCall(ISGetIndices(is, &rows)); 6335 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6336 PetscCall(ISRestoreIndices(is, &rows)); 6337 PetscFunctionReturn(PETSC_SUCCESS); 6338 } 6339 6340 /*@ 6341 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6342 of a set of rows of a matrix. 6343 6344 Collective 6345 6346 Input Parameters: 6347 + mat - the matrix 6348 . numRows - the number of rows to zero 6349 . rows - the global row indices 6350 . diag - value put in the diagonal of the zeroed rows 6351 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6352 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6353 6354 Level: intermediate 6355 6356 Notes: 6357 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6358 6359 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6360 6361 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6362 Krylov method to take advantage of the known solution on the zeroed rows. 6363 6364 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) 6365 from the matrix. 6366 6367 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6368 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6369 formats this does not alter the nonzero structure. 6370 6371 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6372 of the matrix is not changed the values are 6373 merely zeroed. 6374 6375 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6376 formats can optionally remove the main diagonal entry from the 6377 nonzero structure as well, by passing 0.0 as the final argument). 6378 6379 For the parallel case, all processes that share the matrix (i.e., 6380 those in the communicator used for matrix creation) MUST call this 6381 routine, regardless of whether any rows being zeroed are owned by 6382 them. 6383 6384 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6385 list only rows local to itself). 6386 6387 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6388 owns that are to be zeroed. This saves a global synchronization in the implementation. 6389 6390 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6391 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6392 @*/ 6393 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6394 { 6395 PetscFunctionBegin; 6396 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6397 PetscValidType(mat, 1); 6398 if (numRows) PetscAssertPointer(rows, 3); 6399 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6400 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6401 MatCheckPreallocated(mat, 1); 6402 6403 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6404 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6405 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6406 PetscFunctionReturn(PETSC_SUCCESS); 6407 } 6408 6409 /*@ 6410 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6411 of a set of rows of a matrix indicated by an `IS` 6412 6413 Collective 6414 6415 Input Parameters: 6416 + mat - the matrix 6417 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6418 . diag - value put in all diagonals of eliminated rows 6419 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6420 - b - optional vector of right-hand side, that will be adjusted by provided solution 6421 6422 Level: intermediate 6423 6424 Note: 6425 See `MatZeroRows()` for details on how this routine operates. 6426 6427 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6428 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6429 @*/ 6430 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6431 { 6432 PetscInt numRows = 0; 6433 const PetscInt *rows = NULL; 6434 6435 PetscFunctionBegin; 6436 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6437 PetscValidType(mat, 1); 6438 if (is) { 6439 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6440 PetscCall(ISGetLocalSize(is, &numRows)); 6441 PetscCall(ISGetIndices(is, &rows)); 6442 } 6443 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6444 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6445 PetscFunctionReturn(PETSC_SUCCESS); 6446 } 6447 6448 /*@ 6449 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6450 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6451 6452 Collective 6453 6454 Input Parameters: 6455 + mat - the matrix 6456 . numRows - the number of rows to remove 6457 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6458 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6459 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6460 - b - optional vector of right-hand side, that will be adjusted by provided solution 6461 6462 Level: intermediate 6463 6464 Notes: 6465 See `MatZeroRows()` for details on how this routine operates. 6466 6467 The grid coordinates are across the entire grid, not just the local portion 6468 6469 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6470 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6471 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6472 `DM_BOUNDARY_PERIODIC` boundary type. 6473 6474 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 6475 a single value per point) you can skip filling those indices. 6476 6477 Fortran Note: 6478 `idxm` and `idxn` should be declared as 6479 .vb 6480 MatStencil idxm(4, m) 6481 .ve 6482 and the values inserted using 6483 .vb 6484 idxm(MatStencil_i, 1) = i 6485 idxm(MatStencil_j, 1) = j 6486 idxm(MatStencil_k, 1) = k 6487 idxm(MatStencil_c, 1) = c 6488 etc 6489 .ve 6490 6491 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6492 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6493 @*/ 6494 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6495 { 6496 PetscInt dim = mat->stencil.dim; 6497 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6498 PetscInt *dims = mat->stencil.dims + 1; 6499 PetscInt *starts = mat->stencil.starts; 6500 PetscInt *dxm = (PetscInt *)rows; 6501 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6502 6503 PetscFunctionBegin; 6504 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6505 PetscValidType(mat, 1); 6506 if (numRows) PetscAssertPointer(rows, 3); 6507 6508 PetscCall(PetscMalloc1(numRows, &jdxm)); 6509 for (i = 0; i < numRows; ++i) { 6510 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6511 for (j = 0; j < 3 - sdim; ++j) dxm++; 6512 /* Local index in X dir */ 6513 tmp = *dxm++ - starts[0]; 6514 /* Loop over remaining dimensions */ 6515 for (j = 0; j < dim - 1; ++j) { 6516 /* If nonlocal, set index to be negative */ 6517 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6518 /* Update local index */ 6519 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6520 } 6521 /* Skip component slot if necessary */ 6522 if (mat->stencil.noc) dxm++; 6523 /* Local row number */ 6524 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6525 } 6526 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6527 PetscCall(PetscFree(jdxm)); 6528 PetscFunctionReturn(PETSC_SUCCESS); 6529 } 6530 6531 /*@ 6532 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6533 of a set of rows and columns of a matrix. 6534 6535 Collective 6536 6537 Input Parameters: 6538 + mat - the matrix 6539 . numRows - the number of rows/columns to remove 6540 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6541 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6542 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6543 - b - optional vector of right-hand side, that will be adjusted by provided solution 6544 6545 Level: intermediate 6546 6547 Notes: 6548 See `MatZeroRowsColumns()` for details on how this routine operates. 6549 6550 The grid coordinates are across the entire grid, not just the local portion 6551 6552 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6553 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6554 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6555 `DM_BOUNDARY_PERIODIC` boundary type. 6556 6557 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 6558 a single value per point) you can skip filling those indices. 6559 6560 Fortran Note: 6561 `idxm` and `idxn` should be declared as 6562 .vb 6563 MatStencil idxm(4, m) 6564 .ve 6565 and the values inserted using 6566 .vb 6567 idxm(MatStencil_i, 1) = i 6568 idxm(MatStencil_j, 1) = j 6569 idxm(MatStencil_k, 1) = k 6570 idxm(MatStencil_c, 1) = c 6571 etc 6572 .ve 6573 6574 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6575 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6576 @*/ 6577 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6578 { 6579 PetscInt dim = mat->stencil.dim; 6580 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6581 PetscInt *dims = mat->stencil.dims + 1; 6582 PetscInt *starts = mat->stencil.starts; 6583 PetscInt *dxm = (PetscInt *)rows; 6584 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6585 6586 PetscFunctionBegin; 6587 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6588 PetscValidType(mat, 1); 6589 if (numRows) PetscAssertPointer(rows, 3); 6590 6591 PetscCall(PetscMalloc1(numRows, &jdxm)); 6592 for (i = 0; i < numRows; ++i) { 6593 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6594 for (j = 0; j < 3 - sdim; ++j) dxm++; 6595 /* Local index in X dir */ 6596 tmp = *dxm++ - starts[0]; 6597 /* Loop over remaining dimensions */ 6598 for (j = 0; j < dim - 1; ++j) { 6599 /* If nonlocal, set index to be negative */ 6600 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6601 /* Update local index */ 6602 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6603 } 6604 /* Skip component slot if necessary */ 6605 if (mat->stencil.noc) dxm++; 6606 /* Local row number */ 6607 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6608 } 6609 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6610 PetscCall(PetscFree(jdxm)); 6611 PetscFunctionReturn(PETSC_SUCCESS); 6612 } 6613 6614 /*@ 6615 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6616 of a set of rows of a matrix; using local numbering of rows. 6617 6618 Collective 6619 6620 Input Parameters: 6621 + mat - the matrix 6622 . numRows - the number of rows to remove 6623 . rows - the local row indices 6624 . diag - value put in all diagonals of eliminated rows 6625 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6626 - b - optional vector of right-hand side, that will be adjusted by provided solution 6627 6628 Level: intermediate 6629 6630 Notes: 6631 Before calling `MatZeroRowsLocal()`, the user must first set the 6632 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6633 6634 See `MatZeroRows()` for details on how this routine operates. 6635 6636 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6637 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6638 @*/ 6639 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6640 { 6641 PetscFunctionBegin; 6642 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6643 PetscValidType(mat, 1); 6644 if (numRows) PetscAssertPointer(rows, 3); 6645 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6646 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6647 MatCheckPreallocated(mat, 1); 6648 6649 if (mat->ops->zerorowslocal) { 6650 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6651 } else { 6652 IS is, newis; 6653 PetscInt *newRows, nl = 0; 6654 6655 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6656 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_USE_POINTER, &is)); 6657 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6658 PetscCall(ISGetIndices(newis, (const PetscInt **)&newRows)); 6659 for (PetscInt i = 0; i < numRows; i++) 6660 if (newRows[i] > -1) newRows[nl++] = newRows[i]; 6661 PetscUseTypeMethod(mat, zerorows, nl, newRows, diag, x, b); 6662 PetscCall(ISRestoreIndices(newis, (const PetscInt **)&newRows)); 6663 PetscCall(ISDestroy(&newis)); 6664 PetscCall(ISDestroy(&is)); 6665 } 6666 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6667 PetscFunctionReturn(PETSC_SUCCESS); 6668 } 6669 6670 /*@ 6671 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6672 of a set of rows of a matrix; using local numbering of rows. 6673 6674 Collective 6675 6676 Input Parameters: 6677 + mat - the matrix 6678 . is - index set of rows to remove 6679 . diag - value put in all diagonals of eliminated rows 6680 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6681 - b - optional vector of right-hand side, that will be adjusted by provided solution 6682 6683 Level: intermediate 6684 6685 Notes: 6686 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6687 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6688 6689 See `MatZeroRows()` for details on how this routine operates. 6690 6691 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6692 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6693 @*/ 6694 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6695 { 6696 PetscInt numRows; 6697 const PetscInt *rows; 6698 6699 PetscFunctionBegin; 6700 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6701 PetscValidType(mat, 1); 6702 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6703 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6704 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6705 MatCheckPreallocated(mat, 1); 6706 6707 PetscCall(ISGetLocalSize(is, &numRows)); 6708 PetscCall(ISGetIndices(is, &rows)); 6709 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6710 PetscCall(ISRestoreIndices(is, &rows)); 6711 PetscFunctionReturn(PETSC_SUCCESS); 6712 } 6713 6714 /*@ 6715 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6716 of a set of rows and columns of a matrix; using local numbering of rows. 6717 6718 Collective 6719 6720 Input Parameters: 6721 + mat - the matrix 6722 . numRows - the number of rows to remove 6723 . rows - the global row indices 6724 . diag - value put in all diagonals of eliminated rows 6725 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6726 - b - optional vector of right-hand side, that will be adjusted by provided solution 6727 6728 Level: intermediate 6729 6730 Notes: 6731 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6732 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6733 6734 See `MatZeroRowsColumns()` for details on how this routine operates. 6735 6736 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6737 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6738 @*/ 6739 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6740 { 6741 PetscFunctionBegin; 6742 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6743 PetscValidType(mat, 1); 6744 if (numRows) PetscAssertPointer(rows, 3); 6745 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6746 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6747 MatCheckPreallocated(mat, 1); 6748 6749 if (mat->ops->zerorowscolumnslocal) { 6750 PetscUseTypeMethod(mat, zerorowscolumnslocal, numRows, rows, diag, x, b); 6751 } else { 6752 IS is, newis; 6753 PetscInt *newRows, nl = 0; 6754 6755 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6756 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_USE_POINTER, &is)); 6757 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6758 PetscCall(ISGetIndices(newis, (const PetscInt **)&newRows)); 6759 for (PetscInt i = 0; i < numRows; i++) 6760 if (newRows[i] > -1) newRows[nl++] = newRows[i]; 6761 PetscUseTypeMethod(mat, zerorowscolumns, nl, newRows, diag, x, b); 6762 PetscCall(ISRestoreIndices(newis, (const PetscInt **)&newRows)); 6763 PetscCall(ISDestroy(&newis)); 6764 PetscCall(ISDestroy(&is)); 6765 } 6766 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6767 PetscFunctionReturn(PETSC_SUCCESS); 6768 } 6769 6770 /*@ 6771 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6772 of a set of rows and columns of a matrix; using local numbering of rows. 6773 6774 Collective 6775 6776 Input Parameters: 6777 + mat - the matrix 6778 . is - index set of rows to remove 6779 . diag - value put in all diagonals of eliminated rows 6780 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6781 - b - optional vector of right-hand side, that will be adjusted by provided solution 6782 6783 Level: intermediate 6784 6785 Notes: 6786 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6787 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6788 6789 See `MatZeroRowsColumns()` for details on how this routine operates. 6790 6791 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6792 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6793 @*/ 6794 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6795 { 6796 PetscInt numRows; 6797 const PetscInt *rows; 6798 6799 PetscFunctionBegin; 6800 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6801 PetscValidType(mat, 1); 6802 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6803 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6804 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6805 MatCheckPreallocated(mat, 1); 6806 6807 PetscCall(ISGetLocalSize(is, &numRows)); 6808 PetscCall(ISGetIndices(is, &rows)); 6809 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6810 PetscCall(ISRestoreIndices(is, &rows)); 6811 PetscFunctionReturn(PETSC_SUCCESS); 6812 } 6813 6814 /*@ 6815 MatGetSize - Returns the numbers of rows and columns in a matrix. 6816 6817 Not Collective 6818 6819 Input Parameter: 6820 . mat - the matrix 6821 6822 Output Parameters: 6823 + m - the number of global rows 6824 - n - the number of global columns 6825 6826 Level: beginner 6827 6828 Note: 6829 Both output parameters can be `NULL` on input. 6830 6831 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6832 @*/ 6833 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6834 { 6835 PetscFunctionBegin; 6836 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6837 if (m) *m = mat->rmap->N; 6838 if (n) *n = mat->cmap->N; 6839 PetscFunctionReturn(PETSC_SUCCESS); 6840 } 6841 6842 /*@ 6843 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6844 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6845 6846 Not Collective 6847 6848 Input Parameter: 6849 . mat - the matrix 6850 6851 Output Parameters: 6852 + m - the number of local rows, use `NULL` to not obtain this value 6853 - n - the number of local columns, use `NULL` to not obtain this value 6854 6855 Level: beginner 6856 6857 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6858 @*/ 6859 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6860 { 6861 PetscFunctionBegin; 6862 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6863 if (m) PetscAssertPointer(m, 2); 6864 if (n) PetscAssertPointer(n, 3); 6865 if (m) *m = mat->rmap->n; 6866 if (n) *n = mat->cmap->n; 6867 PetscFunctionReturn(PETSC_SUCCESS); 6868 } 6869 6870 /*@ 6871 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6872 vector one multiplies this matrix by that are owned by this processor. 6873 6874 Not Collective, unless matrix has not been allocated, then collective 6875 6876 Input Parameter: 6877 . mat - the matrix 6878 6879 Output Parameters: 6880 + m - the global index of the first local column, use `NULL` to not obtain this value 6881 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6882 6883 Level: developer 6884 6885 Notes: 6886 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6887 6888 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6889 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6890 6891 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6892 the local values in the matrix. 6893 6894 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6895 Layouts](sec_matlayout) for details on matrix layouts. 6896 6897 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6898 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6899 @*/ 6900 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6901 { 6902 PetscFunctionBegin; 6903 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6904 PetscValidType(mat, 1); 6905 if (m) PetscAssertPointer(m, 2); 6906 if (n) PetscAssertPointer(n, 3); 6907 MatCheckPreallocated(mat, 1); 6908 if (m) *m = mat->cmap->rstart; 6909 if (n) *n = mat->cmap->rend; 6910 PetscFunctionReturn(PETSC_SUCCESS); 6911 } 6912 6913 /*@ 6914 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6915 this MPI process. 6916 6917 Not Collective 6918 6919 Input Parameter: 6920 . mat - the matrix 6921 6922 Output Parameters: 6923 + m - the global index of the first local row, use `NULL` to not obtain this value 6924 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6925 6926 Level: beginner 6927 6928 Notes: 6929 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6930 6931 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6932 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6933 6934 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6935 the local values in the matrix. 6936 6937 The high argument is one more than the last element stored locally. 6938 6939 For all matrices it returns the range of matrix rows associated with rows of a vector that 6940 would contain the result of a matrix vector product with this matrix. See [Matrix 6941 Layouts](sec_matlayout) for details on matrix layouts. 6942 6943 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6944 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6945 @*/ 6946 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6947 { 6948 PetscFunctionBegin; 6949 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6950 PetscValidType(mat, 1); 6951 if (m) PetscAssertPointer(m, 2); 6952 if (n) PetscAssertPointer(n, 3); 6953 MatCheckPreallocated(mat, 1); 6954 if (m) *m = mat->rmap->rstart; 6955 if (n) *n = mat->rmap->rend; 6956 PetscFunctionReturn(PETSC_SUCCESS); 6957 } 6958 6959 /*@C 6960 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6961 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6962 6963 Not Collective, unless matrix has not been allocated 6964 6965 Input Parameter: 6966 . mat - the matrix 6967 6968 Output Parameter: 6969 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6970 where `size` is the number of MPI processes used by `mat` 6971 6972 Level: beginner 6973 6974 Notes: 6975 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6976 6977 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6978 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6979 6980 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6981 the local values in the matrix. 6982 6983 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6984 would contain the result of a matrix vector product with this matrix. See [Matrix 6985 Layouts](sec_matlayout) for details on matrix layouts. 6986 6987 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6988 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6989 `DMDAGetGhostCorners()`, `DM` 6990 @*/ 6991 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6992 { 6993 PetscFunctionBegin; 6994 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6995 PetscValidType(mat, 1); 6996 MatCheckPreallocated(mat, 1); 6997 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6998 PetscFunctionReturn(PETSC_SUCCESS); 6999 } 7000 7001 /*@C 7002 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 7003 vector one multiplies this vector by that are owned by each processor. 7004 7005 Not Collective, unless matrix has not been allocated 7006 7007 Input Parameter: 7008 . mat - the matrix 7009 7010 Output Parameter: 7011 . ranges - start of each processors portion plus one more than the total length at the end 7012 7013 Level: beginner 7014 7015 Notes: 7016 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 7017 7018 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 7019 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 7020 7021 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 7022 the local values in the matrix. 7023 7024 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 7025 Layouts](sec_matlayout) for details on matrix layouts. 7026 7027 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 7028 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 7029 `DMDAGetGhostCorners()`, `DM` 7030 @*/ 7031 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 7032 { 7033 PetscFunctionBegin; 7034 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7035 PetscValidType(mat, 1); 7036 MatCheckPreallocated(mat, 1); 7037 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 7038 PetscFunctionReturn(PETSC_SUCCESS); 7039 } 7040 7041 /*@ 7042 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7043 7044 Not Collective 7045 7046 Input Parameter: 7047 . A - matrix 7048 7049 Output Parameters: 7050 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7051 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7052 7053 Level: intermediate 7054 7055 Note: 7056 You should call `ISDestroy()` on the returned `IS` 7057 7058 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7059 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7060 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7061 details on matrix layouts. 7062 7063 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7064 @*/ 7065 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7066 { 7067 PetscErrorCode (*f)(Mat, IS *, IS *); 7068 7069 PetscFunctionBegin; 7070 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7071 PetscValidType(A, 1); 7072 MatCheckPreallocated(A, 1); 7073 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7074 if (f) { 7075 PetscCall((*f)(A, rows, cols)); 7076 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7077 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7078 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7079 } 7080 PetscFunctionReturn(PETSC_SUCCESS); 7081 } 7082 7083 /*@ 7084 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7085 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7086 to complete the factorization. 7087 7088 Collective 7089 7090 Input Parameters: 7091 + fact - the factorized matrix obtained with `MatGetFactor()` 7092 . mat - the matrix 7093 . row - row permutation 7094 . col - column permutation 7095 - info - structure containing 7096 .vb 7097 levels - number of levels of fill. 7098 expected fill - as ratio of original fill. 7099 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7100 missing diagonal entries) 7101 .ve 7102 7103 Level: developer 7104 7105 Notes: 7106 See [Matrix Factorization](sec_matfactor) for additional information. 7107 7108 Most users should employ the `KSP` interface for linear solvers 7109 instead of working directly with matrix algebra routines such as this. 7110 See, e.g., `KSPCreate()`. 7111 7112 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7113 7114 Fortran Note: 7115 A valid (non-null) `info` argument must be provided 7116 7117 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7118 `MatGetOrdering()`, `MatFactorInfo` 7119 @*/ 7120 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7121 { 7122 PetscFunctionBegin; 7123 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7124 PetscValidType(mat, 2); 7125 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7126 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7127 PetscAssertPointer(info, 5); 7128 PetscAssertPointer(fact, 1); 7129 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7130 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7131 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7132 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7133 MatCheckPreallocated(mat, 2); 7134 7135 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7136 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7137 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7138 PetscFunctionReturn(PETSC_SUCCESS); 7139 } 7140 7141 /*@ 7142 MatICCFactorSymbolic - Performs symbolic incomplete 7143 Cholesky factorization for a symmetric matrix. Use 7144 `MatCholeskyFactorNumeric()` to complete the factorization. 7145 7146 Collective 7147 7148 Input Parameters: 7149 + fact - the factorized matrix obtained with `MatGetFactor()` 7150 . mat - the matrix to be factored 7151 . perm - row and column permutation 7152 - info - structure containing 7153 .vb 7154 levels - number of levels of fill. 7155 expected fill - as ratio of original fill. 7156 .ve 7157 7158 Level: developer 7159 7160 Notes: 7161 Most users should employ the `KSP` interface for linear solvers 7162 instead of working directly with matrix algebra routines such as this. 7163 See, e.g., `KSPCreate()`. 7164 7165 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7166 7167 Fortran Note: 7168 A valid (non-null) `info` argument must be provided 7169 7170 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7171 @*/ 7172 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7173 { 7174 PetscFunctionBegin; 7175 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7176 PetscValidType(mat, 2); 7177 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7178 PetscAssertPointer(info, 4); 7179 PetscAssertPointer(fact, 1); 7180 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7181 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7182 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7183 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7184 MatCheckPreallocated(mat, 2); 7185 7186 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7187 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7188 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7189 PetscFunctionReturn(PETSC_SUCCESS); 7190 } 7191 7192 /*@C 7193 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7194 points to an array of valid matrices, they may be reused to store the new 7195 submatrices. 7196 7197 Collective 7198 7199 Input Parameters: 7200 + mat - the matrix 7201 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7202 . irow - index set of rows to extract 7203 . icol - index set of columns to extract 7204 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7205 7206 Output Parameter: 7207 . submat - the array of submatrices 7208 7209 Level: advanced 7210 7211 Notes: 7212 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7213 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7214 to extract a parallel submatrix. 7215 7216 Some matrix types place restrictions on the row and column 7217 indices, such as that they be sorted or that they be equal to each other. 7218 7219 The index sets may not have duplicate entries. 7220 7221 When extracting submatrices from a parallel matrix, each processor can 7222 form a different submatrix by setting the rows and columns of its 7223 individual index sets according to the local submatrix desired. 7224 7225 When finished using the submatrices, the user should destroy 7226 them with `MatDestroySubMatrices()`. 7227 7228 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7229 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7230 7231 This routine creates the matrices in submat; you should NOT create them before 7232 calling it. It also allocates the array of matrix pointers submat. 7233 7234 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7235 request one row/column in a block, they must request all rows/columns that are in 7236 that block. For example, if the block size is 2 you cannot request just row 0 and 7237 column 0. 7238 7239 Fortran Note: 7240 .vb 7241 Mat, pointer :: submat(:) 7242 .ve 7243 7244 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7245 @*/ 7246 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7247 { 7248 PetscInt i; 7249 PetscBool eq; 7250 7251 PetscFunctionBegin; 7252 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7253 PetscValidType(mat, 1); 7254 if (n) { 7255 PetscAssertPointer(irow, 3); 7256 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7257 PetscAssertPointer(icol, 4); 7258 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7259 } 7260 PetscAssertPointer(submat, 6); 7261 if (n && scall == MAT_REUSE_MATRIX) { 7262 PetscAssertPointer(*submat, 6); 7263 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7264 } 7265 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7266 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7267 MatCheckPreallocated(mat, 1); 7268 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7269 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7270 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7271 for (i = 0; i < n; i++) { 7272 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7273 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7274 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7275 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7276 if (mat->boundtocpu && mat->bindingpropagates) { 7277 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7278 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7279 } 7280 #endif 7281 } 7282 PetscFunctionReturn(PETSC_SUCCESS); 7283 } 7284 7285 /*@C 7286 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7287 7288 Collective 7289 7290 Input Parameters: 7291 + mat - the matrix 7292 . n - the number of submatrixes to be extracted 7293 . irow - index set of rows to extract 7294 . icol - index set of columns to extract 7295 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7296 7297 Output Parameter: 7298 . submat - the array of submatrices 7299 7300 Level: advanced 7301 7302 Note: 7303 This is used by `PCGASM` 7304 7305 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7306 @*/ 7307 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7308 { 7309 PetscInt i; 7310 PetscBool eq; 7311 7312 PetscFunctionBegin; 7313 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7314 PetscValidType(mat, 1); 7315 if (n) { 7316 PetscAssertPointer(irow, 3); 7317 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7318 PetscAssertPointer(icol, 4); 7319 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7320 } 7321 PetscAssertPointer(submat, 6); 7322 if (n && scall == MAT_REUSE_MATRIX) { 7323 PetscAssertPointer(*submat, 6); 7324 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7325 } 7326 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7327 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7328 MatCheckPreallocated(mat, 1); 7329 7330 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7331 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7332 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7333 for (i = 0; i < n; i++) { 7334 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7335 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7336 } 7337 PetscFunctionReturn(PETSC_SUCCESS); 7338 } 7339 7340 /*@C 7341 MatDestroyMatrices - Destroys an array of matrices 7342 7343 Collective 7344 7345 Input Parameters: 7346 + n - the number of local matrices 7347 - mat - the matrices (this is a pointer to the array of matrices) 7348 7349 Level: advanced 7350 7351 Notes: 7352 Frees not only the matrices, but also the array that contains the matrices 7353 7354 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7355 7356 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7357 @*/ 7358 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7359 { 7360 PetscInt i; 7361 7362 PetscFunctionBegin; 7363 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7364 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7365 PetscAssertPointer(mat, 2); 7366 7367 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7368 7369 /* memory is allocated even if n = 0 */ 7370 PetscCall(PetscFree(*mat)); 7371 PetscFunctionReturn(PETSC_SUCCESS); 7372 } 7373 7374 /*@C 7375 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7376 7377 Collective 7378 7379 Input Parameters: 7380 + n - the number of local matrices 7381 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7382 7383 Level: advanced 7384 7385 Note: 7386 Frees not only the matrices, but also the array that contains the matrices 7387 7388 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7389 @*/ 7390 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7391 { 7392 Mat mat0; 7393 7394 PetscFunctionBegin; 7395 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7396 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7397 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7398 PetscAssertPointer(mat, 2); 7399 7400 mat0 = (*mat)[0]; 7401 if (mat0 && mat0->ops->destroysubmatrices) { 7402 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7403 } else { 7404 PetscCall(MatDestroyMatrices(n, mat)); 7405 } 7406 PetscFunctionReturn(PETSC_SUCCESS); 7407 } 7408 7409 /*@ 7410 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7411 7412 Collective 7413 7414 Input Parameter: 7415 . mat - the matrix 7416 7417 Output Parameter: 7418 . matstruct - the sequential matrix with the nonzero structure of `mat` 7419 7420 Level: developer 7421 7422 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7423 @*/ 7424 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7425 { 7426 PetscFunctionBegin; 7427 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7428 PetscAssertPointer(matstruct, 2); 7429 7430 PetscValidType(mat, 1); 7431 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7432 MatCheckPreallocated(mat, 1); 7433 7434 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7435 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7436 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7437 PetscFunctionReturn(PETSC_SUCCESS); 7438 } 7439 7440 /*@C 7441 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7442 7443 Collective 7444 7445 Input Parameter: 7446 . mat - the matrix 7447 7448 Level: advanced 7449 7450 Note: 7451 This is not needed, one can just call `MatDestroy()` 7452 7453 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7454 @*/ 7455 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7456 { 7457 PetscFunctionBegin; 7458 PetscAssertPointer(mat, 1); 7459 PetscCall(MatDestroy(mat)); 7460 PetscFunctionReturn(PETSC_SUCCESS); 7461 } 7462 7463 /*@ 7464 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7465 replaces the index sets by larger ones that represent submatrices with 7466 additional overlap. 7467 7468 Collective 7469 7470 Input Parameters: 7471 + mat - the matrix 7472 . n - the number of index sets 7473 . is - the array of index sets (these index sets will changed during the call) 7474 - ov - the additional overlap requested 7475 7476 Options Database Key: 7477 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7478 7479 Level: developer 7480 7481 Note: 7482 The computed overlap preserves the matrix block sizes when the blocks are square. 7483 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7484 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7485 7486 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7487 @*/ 7488 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7489 { 7490 PetscInt i, bs, cbs; 7491 7492 PetscFunctionBegin; 7493 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7494 PetscValidType(mat, 1); 7495 PetscValidLogicalCollectiveInt(mat, n, 2); 7496 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7497 if (n) { 7498 PetscAssertPointer(is, 3); 7499 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7500 } 7501 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7502 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7503 MatCheckPreallocated(mat, 1); 7504 7505 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7506 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7507 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7508 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7509 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7510 if (bs == cbs) { 7511 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7512 } 7513 PetscFunctionReturn(PETSC_SUCCESS); 7514 } 7515 7516 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7517 7518 /*@ 7519 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7520 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7521 additional overlap. 7522 7523 Collective 7524 7525 Input Parameters: 7526 + mat - the matrix 7527 . n - the number of index sets 7528 . is - the array of index sets (these index sets will changed during the call) 7529 - ov - the additional overlap requested 7530 7531 ` Options Database Key: 7532 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7533 7534 Level: developer 7535 7536 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7537 @*/ 7538 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7539 { 7540 PetscInt i; 7541 7542 PetscFunctionBegin; 7543 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7544 PetscValidType(mat, 1); 7545 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7546 if (n) { 7547 PetscAssertPointer(is, 3); 7548 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7549 } 7550 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7551 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7552 MatCheckPreallocated(mat, 1); 7553 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7554 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7555 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7556 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7557 PetscFunctionReturn(PETSC_SUCCESS); 7558 } 7559 7560 /*@ 7561 MatGetBlockSize - Returns the matrix block size. 7562 7563 Not Collective 7564 7565 Input Parameter: 7566 . mat - the matrix 7567 7568 Output Parameter: 7569 . bs - block size 7570 7571 Level: intermediate 7572 7573 Notes: 7574 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7575 7576 If the block size has not been set yet this routine returns 1. 7577 7578 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7579 @*/ 7580 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7581 { 7582 PetscFunctionBegin; 7583 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7584 PetscAssertPointer(bs, 2); 7585 *bs = mat->rmap->bs; 7586 PetscFunctionReturn(PETSC_SUCCESS); 7587 } 7588 7589 /*@ 7590 MatGetBlockSizes - Returns the matrix block row and column sizes. 7591 7592 Not Collective 7593 7594 Input Parameter: 7595 . mat - the matrix 7596 7597 Output Parameters: 7598 + rbs - row block size 7599 - cbs - column block size 7600 7601 Level: intermediate 7602 7603 Notes: 7604 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7605 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7606 7607 If a block size has not been set yet this routine returns 1. 7608 7609 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7610 @*/ 7611 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7612 { 7613 PetscFunctionBegin; 7614 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7615 if (rbs) PetscAssertPointer(rbs, 2); 7616 if (cbs) PetscAssertPointer(cbs, 3); 7617 if (rbs) *rbs = mat->rmap->bs; 7618 if (cbs) *cbs = mat->cmap->bs; 7619 PetscFunctionReturn(PETSC_SUCCESS); 7620 } 7621 7622 /*@ 7623 MatSetBlockSize - Sets the matrix block size. 7624 7625 Logically Collective 7626 7627 Input Parameters: 7628 + mat - the matrix 7629 - bs - block size 7630 7631 Level: intermediate 7632 7633 Notes: 7634 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7635 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7636 7637 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7638 is compatible with the matrix local sizes. 7639 7640 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7641 @*/ 7642 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7643 { 7644 PetscFunctionBegin; 7645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7646 PetscValidLogicalCollectiveInt(mat, bs, 2); 7647 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7648 PetscFunctionReturn(PETSC_SUCCESS); 7649 } 7650 7651 typedef struct { 7652 PetscInt n; 7653 IS *is; 7654 Mat *mat; 7655 PetscObjectState nonzerostate; 7656 Mat C; 7657 } EnvelopeData; 7658 7659 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7660 { 7661 EnvelopeData *edata = (EnvelopeData *)*ptr; 7662 7663 PetscFunctionBegin; 7664 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7665 PetscCall(PetscFree(edata->is)); 7666 PetscCall(PetscFree(edata)); 7667 PetscFunctionReturn(PETSC_SUCCESS); 7668 } 7669 7670 /*@ 7671 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7672 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7673 7674 Collective 7675 7676 Input Parameter: 7677 . mat - the matrix 7678 7679 Level: intermediate 7680 7681 Notes: 7682 There can be zeros within the blocks 7683 7684 The blocks can overlap between processes, including laying on more than two processes 7685 7686 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7687 @*/ 7688 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7689 { 7690 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7691 PetscInt *diag, *odiag, sc; 7692 VecScatter scatter; 7693 PetscScalar *seqv; 7694 const PetscScalar *parv; 7695 const PetscInt *ia, *ja; 7696 PetscBool set, flag, done; 7697 Mat AA = mat, A; 7698 MPI_Comm comm; 7699 PetscMPIInt rank, size, tag; 7700 MPI_Status status; 7701 PetscContainer container; 7702 EnvelopeData *edata; 7703 Vec seq, par; 7704 IS isglobal; 7705 7706 PetscFunctionBegin; 7707 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7708 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7709 if (!set || !flag) { 7710 /* TODO: only needs nonzero structure of transpose */ 7711 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7712 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7713 } 7714 PetscCall(MatAIJGetLocalMat(AA, &A)); 7715 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7716 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7717 7718 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7719 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7720 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7721 PetscCallMPI(MPI_Comm_size(comm, &size)); 7722 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7723 7724 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7725 7726 if (rank > 0) { 7727 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7728 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7729 } 7730 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7731 for (i = 0; i < n; i++) { 7732 env = PetscMax(env, ja[ia[i + 1] - 1]); 7733 II = rstart + i; 7734 if (env == II) { 7735 starts[lblocks] = tbs; 7736 sizes[lblocks++] = 1 + II - tbs; 7737 tbs = 1 + II; 7738 } 7739 } 7740 if (rank < size - 1) { 7741 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7742 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7743 } 7744 7745 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7746 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7747 PetscCall(MatDestroy(&A)); 7748 7749 PetscCall(PetscNew(&edata)); 7750 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7751 edata->n = lblocks; 7752 /* create IS needed for extracting blocks from the original matrix */ 7753 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7754 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7755 7756 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7757 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7758 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7759 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7760 PetscCall(MatSetType(edata->C, MATAIJ)); 7761 7762 /* Communicate the start and end of each row, from each block to the correct rank */ 7763 /* TODO: Use PetscSF instead of VecScatter */ 7764 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7765 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7766 PetscCall(VecGetArrayWrite(seq, &seqv)); 7767 for (PetscInt i = 0; i < lblocks; i++) { 7768 for (PetscInt j = 0; j < sizes[i]; j++) { 7769 seqv[cnt] = starts[i]; 7770 seqv[cnt + 1] = starts[i] + sizes[i]; 7771 cnt += 2; 7772 } 7773 } 7774 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7775 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7776 sc -= cnt; 7777 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7778 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7779 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7780 PetscCall(ISDestroy(&isglobal)); 7781 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7782 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7783 PetscCall(VecScatterDestroy(&scatter)); 7784 PetscCall(VecDestroy(&seq)); 7785 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7786 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7787 PetscCall(VecGetArrayRead(par, &parv)); 7788 cnt = 0; 7789 PetscCall(MatGetSize(mat, NULL, &n)); 7790 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7791 PetscInt start, end, d = 0, od = 0; 7792 7793 start = (PetscInt)PetscRealPart(parv[cnt]); 7794 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7795 cnt += 2; 7796 7797 if (start < cstart) { 7798 od += cstart - start + n - cend; 7799 d += cend - cstart; 7800 } else if (start < cend) { 7801 od += n - cend; 7802 d += cend - start; 7803 } else od += n - start; 7804 if (end <= cstart) { 7805 od -= cstart - end + n - cend; 7806 d -= cend - cstart; 7807 } else if (end < cend) { 7808 od -= n - cend; 7809 d -= cend - end; 7810 } else od -= n - end; 7811 7812 odiag[i] = od; 7813 diag[i] = d; 7814 } 7815 PetscCall(VecRestoreArrayRead(par, &parv)); 7816 PetscCall(VecDestroy(&par)); 7817 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7818 PetscCall(PetscFree2(diag, odiag)); 7819 PetscCall(PetscFree2(sizes, starts)); 7820 7821 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7822 PetscCall(PetscContainerSetPointer(container, edata)); 7823 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7824 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7825 PetscCall(PetscObjectDereference((PetscObject)container)); 7826 PetscFunctionReturn(PETSC_SUCCESS); 7827 } 7828 7829 /*@ 7830 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7831 7832 Collective 7833 7834 Input Parameters: 7835 + A - the matrix 7836 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7837 7838 Output Parameter: 7839 . C - matrix with inverted block diagonal of `A` 7840 7841 Level: advanced 7842 7843 Note: 7844 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7845 7846 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7847 @*/ 7848 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7849 { 7850 PetscContainer container; 7851 EnvelopeData *edata; 7852 PetscObjectState nonzerostate; 7853 7854 PetscFunctionBegin; 7855 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7856 if (!container) { 7857 PetscCall(MatComputeVariableBlockEnvelope(A)); 7858 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7859 } 7860 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7861 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7862 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7863 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7864 7865 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7866 *C = edata->C; 7867 7868 for (PetscInt i = 0; i < edata->n; i++) { 7869 Mat D; 7870 PetscScalar *dvalues; 7871 7872 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7873 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7874 PetscCall(MatSeqDenseInvert(D)); 7875 PetscCall(MatDenseGetArray(D, &dvalues)); 7876 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7877 PetscCall(MatDestroy(&D)); 7878 } 7879 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7880 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7881 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7882 PetscFunctionReturn(PETSC_SUCCESS); 7883 } 7884 7885 /*@ 7886 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7887 7888 Not Collective 7889 7890 Input Parameters: 7891 + mat - the matrix 7892 . nblocks - the number of blocks on this process, each block can only exist on a single process 7893 - bsizes - the block sizes 7894 7895 Level: intermediate 7896 7897 Notes: 7898 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7899 7900 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. 7901 7902 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7903 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7904 @*/ 7905 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7906 { 7907 PetscInt ncnt = 0, nlocal; 7908 7909 PetscFunctionBegin; 7910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7911 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7912 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); 7913 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7914 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); 7915 PetscCall(PetscFree(mat->bsizes)); 7916 mat->nblocks = nblocks; 7917 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7918 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7919 PetscFunctionReturn(PETSC_SUCCESS); 7920 } 7921 7922 /*@C 7923 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7924 7925 Not Collective; No Fortran Support 7926 7927 Input Parameter: 7928 . mat - the matrix 7929 7930 Output Parameters: 7931 + nblocks - the number of blocks on this process 7932 - bsizes - the block sizes 7933 7934 Level: intermediate 7935 7936 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7937 @*/ 7938 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7939 { 7940 PetscFunctionBegin; 7941 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7942 if (nblocks) *nblocks = mat->nblocks; 7943 if (bsizes) *bsizes = mat->bsizes; 7944 PetscFunctionReturn(PETSC_SUCCESS); 7945 } 7946 7947 /*@ 7948 MatSelectVariableBlockSizes - When creating a submatrix, pass on the variable block sizes 7949 7950 Not Collective 7951 7952 Input Parameter: 7953 + subA - the submatrix 7954 . A - the original matrix 7955 - isrow - The `IS` of selected rows for the submatrix, must be sorted 7956 7957 Level: developer 7958 7959 Notes: 7960 If the index set is not sorted or contains off-process entries, this function will do nothing. 7961 7962 .seealso: [](ch_matrices), `Mat`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7963 @*/ 7964 PetscErrorCode MatSelectVariableBlockSizes(Mat subA, Mat A, IS isrow) 7965 { 7966 const PetscInt *rows; 7967 PetscInt n, rStart, rEnd, Nb = 0; 7968 PetscBool flg = A->bsizes ? PETSC_TRUE : PETSC_FALSE; 7969 7970 PetscFunctionBegin; 7971 // The code for block size extraction does not support an unsorted IS 7972 if (flg) PetscCall(ISSorted(isrow, &flg)); 7973 // We don't support originally off-diagonal blocks 7974 if (flg) { 7975 PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd)); 7976 PetscCall(ISGetLocalSize(isrow, &n)); 7977 PetscCall(ISGetIndices(isrow, &rows)); 7978 for (PetscInt i = 0; i < n && flg; ++i) { 7979 if (rows[i] < rStart || rows[i] >= rEnd) flg = PETSC_FALSE; 7980 } 7981 PetscCall(ISRestoreIndices(isrow, &rows)); 7982 } 7983 // quiet return if we can't extract block size 7984 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)subA))); 7985 if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 7986 7987 // extract block sizes 7988 PetscCall(ISGetIndices(isrow, &rows)); 7989 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7990 PetscBool occupied = PETSC_FALSE; 7991 7992 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7993 const PetscInt row = gr + br; 7994 7995 if (i == n) break; 7996 if (rows[i] == row) { 7997 occupied = PETSC_TRUE; 7998 ++i; 7999 } 8000 while (i < n && rows[i] < row) ++i; 8001 } 8002 gr += A->bsizes[b]; 8003 if (occupied) ++Nb; 8004 } 8005 subA->nblocks = Nb; 8006 PetscCall(PetscFree(subA->bsizes)); 8007 PetscCall(PetscMalloc1(subA->nblocks, &subA->bsizes)); 8008 PetscInt sb = 0; 8009 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 8010 if (sb < subA->nblocks) subA->bsizes[sb] = 0; 8011 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 8012 const PetscInt row = gr + br; 8013 8014 if (i == n) break; 8015 if (rows[i] == row) { 8016 ++subA->bsizes[sb]; 8017 ++i; 8018 } 8019 while (i < n && rows[i] < row) ++i; 8020 } 8021 gr += A->bsizes[b]; 8022 if (sb < subA->nblocks && subA->bsizes[sb]) ++sb; 8023 } 8024 PetscCheck(sb == subA->nblocks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of blocks %" PetscInt_FMT " != %" PetscInt_FMT, sb, subA->nblocks); 8025 PetscInt nlocal, ncnt = 0; 8026 PetscCall(MatGetLocalSize(subA, &nlocal, NULL)); 8027 PetscCheck(subA->nblocks >= 0 && subA->nblocks <= nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks %" PetscInt_FMT " is not in [0, %" PetscInt_FMT "]", subA->nblocks, nlocal); 8028 for (PetscInt i = 0; i < subA->nblocks; i++) ncnt += subA->bsizes[i]; 8029 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); 8030 PetscCall(ISRestoreIndices(isrow, &rows)); 8031 PetscFunctionReturn(PETSC_SUCCESS); 8032 } 8033 8034 /*@ 8035 MatSetBlockSizes - Sets the matrix block row and column sizes. 8036 8037 Logically Collective 8038 8039 Input Parameters: 8040 + mat - the matrix 8041 . rbs - row block size 8042 - cbs - column block size 8043 8044 Level: intermediate 8045 8046 Notes: 8047 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 8048 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 8049 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 8050 8051 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 8052 are compatible with the matrix local sizes. 8053 8054 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 8055 8056 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 8057 @*/ 8058 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8059 { 8060 PetscFunctionBegin; 8061 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8062 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8063 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8064 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8065 if (mat->rmap->refcnt) { 8066 ISLocalToGlobalMapping l2g = NULL; 8067 PetscLayout nmap = NULL; 8068 8069 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8070 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8071 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8072 mat->rmap = nmap; 8073 mat->rmap->mapping = l2g; 8074 } 8075 if (mat->cmap->refcnt) { 8076 ISLocalToGlobalMapping l2g = NULL; 8077 PetscLayout nmap = NULL; 8078 8079 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8080 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8081 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8082 mat->cmap = nmap; 8083 mat->cmap->mapping = l2g; 8084 } 8085 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8086 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8087 PetscFunctionReturn(PETSC_SUCCESS); 8088 } 8089 8090 /*@ 8091 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8092 8093 Logically Collective 8094 8095 Input Parameters: 8096 + mat - the matrix 8097 . fromRow - matrix from which to copy row block size 8098 - fromCol - matrix from which to copy column block size (can be same as `fromRow`) 8099 8100 Level: developer 8101 8102 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8103 @*/ 8104 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8105 { 8106 PetscFunctionBegin; 8107 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8108 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8109 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8110 PetscTryTypeMethod(mat, setblocksizes, fromRow->rmap->bs, fromCol->cmap->bs); 8111 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8112 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8113 PetscFunctionReturn(PETSC_SUCCESS); 8114 } 8115 8116 /*@ 8117 MatResidual - Default routine to calculate the residual r = b - Ax 8118 8119 Collective 8120 8121 Input Parameters: 8122 + mat - the matrix 8123 . b - the right-hand-side 8124 - x - the approximate solution 8125 8126 Output Parameter: 8127 . r - location to store the residual 8128 8129 Level: developer 8130 8131 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8132 @*/ 8133 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8134 { 8135 PetscFunctionBegin; 8136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8137 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8138 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8139 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8140 PetscValidType(mat, 1); 8141 MatCheckPreallocated(mat, 1); 8142 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8143 if (!mat->ops->residual) { 8144 PetscCall(MatMult(mat, x, r)); 8145 PetscCall(VecAYPX(r, -1.0, b)); 8146 } else { 8147 PetscUseTypeMethod(mat, residual, b, x, r); 8148 } 8149 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8150 PetscFunctionReturn(PETSC_SUCCESS); 8151 } 8152 8153 /*@C 8154 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8155 8156 Collective 8157 8158 Input Parameters: 8159 + mat - the matrix 8160 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8161 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8162 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8163 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8164 always used. 8165 8166 Output Parameters: 8167 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8168 . 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 8169 . ja - the column indices, use `NULL` if not needed 8170 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8171 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8172 8173 Level: developer 8174 8175 Notes: 8176 You CANNOT change any of the ia[] or ja[] values. 8177 8178 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8179 8180 Fortran Notes: 8181 Use 8182 .vb 8183 PetscInt, pointer :: ia(:),ja(:) 8184 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8185 ! Access the ith and jth entries via ia(i) and ja(j) 8186 .ve 8187 8188 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8189 @*/ 8190 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8191 { 8192 PetscFunctionBegin; 8193 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8194 PetscValidType(mat, 1); 8195 if (n) PetscAssertPointer(n, 5); 8196 if (ia) PetscAssertPointer(ia, 6); 8197 if (ja) PetscAssertPointer(ja, 7); 8198 if (done) PetscAssertPointer(done, 8); 8199 MatCheckPreallocated(mat, 1); 8200 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8201 else { 8202 if (done) *done = PETSC_TRUE; 8203 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8204 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8205 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8206 } 8207 PetscFunctionReturn(PETSC_SUCCESS); 8208 } 8209 8210 /*@C 8211 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8212 8213 Collective 8214 8215 Input Parameters: 8216 + mat - the matrix 8217 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8218 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8219 symmetrized 8220 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8221 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8222 always used. 8223 8224 Output Parameters: 8225 + n - number of columns in the (possibly compressed) matrix 8226 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8227 . ja - the row indices 8228 - done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8229 8230 Level: developer 8231 8232 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8233 @*/ 8234 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8235 { 8236 PetscFunctionBegin; 8237 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8238 PetscValidType(mat, 1); 8239 PetscAssertPointer(n, 5); 8240 if (ia) PetscAssertPointer(ia, 6); 8241 if (ja) PetscAssertPointer(ja, 7); 8242 PetscAssertPointer(done, 8); 8243 MatCheckPreallocated(mat, 1); 8244 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8245 else { 8246 *done = PETSC_TRUE; 8247 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8248 } 8249 PetscFunctionReturn(PETSC_SUCCESS); 8250 } 8251 8252 /*@C 8253 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8254 8255 Collective 8256 8257 Input Parameters: 8258 + mat - the matrix 8259 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8260 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8261 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8262 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8263 always used. 8264 . n - size of (possibly compressed) matrix 8265 . ia - the row pointers 8266 - ja - the column indices 8267 8268 Output Parameter: 8269 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8270 8271 Level: developer 8272 8273 Note: 8274 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8275 us of the array after it has been restored. If you pass `NULL`, it will 8276 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8277 8278 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8279 @*/ 8280 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8281 { 8282 PetscFunctionBegin; 8283 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8284 PetscValidType(mat, 1); 8285 if (ia) PetscAssertPointer(ia, 6); 8286 if (ja) PetscAssertPointer(ja, 7); 8287 if (done) PetscAssertPointer(done, 8); 8288 MatCheckPreallocated(mat, 1); 8289 8290 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8291 else { 8292 if (done) *done = PETSC_TRUE; 8293 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8294 if (n) *n = 0; 8295 if (ia) *ia = NULL; 8296 if (ja) *ja = NULL; 8297 } 8298 PetscFunctionReturn(PETSC_SUCCESS); 8299 } 8300 8301 /*@C 8302 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8303 8304 Collective 8305 8306 Input Parameters: 8307 + mat - the matrix 8308 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8309 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8310 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8311 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8312 always used. 8313 8314 Output Parameters: 8315 + n - size of (possibly compressed) matrix 8316 . ia - the column pointers 8317 . ja - the row indices 8318 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8319 8320 Level: developer 8321 8322 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8323 @*/ 8324 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8325 { 8326 PetscFunctionBegin; 8327 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8328 PetscValidType(mat, 1); 8329 if (ia) PetscAssertPointer(ia, 6); 8330 if (ja) PetscAssertPointer(ja, 7); 8331 PetscAssertPointer(done, 8); 8332 MatCheckPreallocated(mat, 1); 8333 8334 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8335 else { 8336 *done = PETSC_TRUE; 8337 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8338 if (n) *n = 0; 8339 if (ia) *ia = NULL; 8340 if (ja) *ja = NULL; 8341 } 8342 PetscFunctionReturn(PETSC_SUCCESS); 8343 } 8344 8345 /*@ 8346 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8347 `MatGetColumnIJ()`. 8348 8349 Collective 8350 8351 Input Parameters: 8352 + mat - the matrix 8353 . ncolors - maximum color value 8354 . n - number of entries in colorarray 8355 - colorarray - array indicating color for each column 8356 8357 Output Parameter: 8358 . iscoloring - coloring generated using colorarray information 8359 8360 Level: developer 8361 8362 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8363 @*/ 8364 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8365 { 8366 PetscFunctionBegin; 8367 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8368 PetscValidType(mat, 1); 8369 PetscAssertPointer(colorarray, 4); 8370 PetscAssertPointer(iscoloring, 5); 8371 MatCheckPreallocated(mat, 1); 8372 8373 if (!mat->ops->coloringpatch) { 8374 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8375 } else { 8376 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8377 } 8378 PetscFunctionReturn(PETSC_SUCCESS); 8379 } 8380 8381 /*@ 8382 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8383 8384 Logically Collective 8385 8386 Input Parameter: 8387 . mat - the factored matrix to be reset 8388 8389 Level: developer 8390 8391 Notes: 8392 This routine should be used only with factored matrices formed by in-place 8393 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8394 format). This option can save memory, for example, when solving nonlinear 8395 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8396 ILU(0) preconditioner. 8397 8398 One can specify in-place ILU(0) factorization by calling 8399 .vb 8400 PCType(pc,PCILU); 8401 PCFactorSeUseInPlace(pc); 8402 .ve 8403 or by using the options -pc_type ilu -pc_factor_in_place 8404 8405 In-place factorization ILU(0) can also be used as a local 8406 solver for the blocks within the block Jacobi or additive Schwarz 8407 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8408 for details on setting local solver options. 8409 8410 Most users should employ the `KSP` interface for linear solvers 8411 instead of working directly with matrix algebra routines such as this. 8412 See, e.g., `KSPCreate()`. 8413 8414 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8415 @*/ 8416 PetscErrorCode MatSetUnfactored(Mat mat) 8417 { 8418 PetscFunctionBegin; 8419 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8420 PetscValidType(mat, 1); 8421 MatCheckPreallocated(mat, 1); 8422 mat->factortype = MAT_FACTOR_NONE; 8423 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8424 PetscUseTypeMethod(mat, setunfactored); 8425 PetscFunctionReturn(PETSC_SUCCESS); 8426 } 8427 8428 /*@ 8429 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8430 as the original matrix. 8431 8432 Collective 8433 8434 Input Parameters: 8435 + mat - the original matrix 8436 . isrow - parallel `IS` containing the rows this processor should obtain 8437 . 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. 8438 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8439 8440 Output Parameter: 8441 . newmat - the new submatrix, of the same type as the original matrix 8442 8443 Level: advanced 8444 8445 Notes: 8446 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8447 8448 Some matrix types place restrictions on the row and column indices, such 8449 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; 8450 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8451 8452 The index sets may not have duplicate entries. 8453 8454 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8455 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8456 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8457 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8458 you are finished using it. 8459 8460 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8461 the input matrix. 8462 8463 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8464 8465 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8466 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8467 8468 Example usage: 8469 Consider the following 8x8 matrix with 34 non-zero values, that is 8470 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8471 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8472 as follows 8473 .vb 8474 1 2 0 | 0 3 0 | 0 4 8475 Proc0 0 5 6 | 7 0 0 | 8 0 8476 9 0 10 | 11 0 0 | 12 0 8477 ------------------------------------- 8478 13 0 14 | 15 16 17 | 0 0 8479 Proc1 0 18 0 | 19 20 21 | 0 0 8480 0 0 0 | 22 23 0 | 24 0 8481 ------------------------------------- 8482 Proc2 25 26 27 | 0 0 28 | 29 0 8483 30 0 0 | 31 32 33 | 0 34 8484 .ve 8485 8486 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8487 8488 .vb 8489 2 0 | 0 3 0 | 0 8490 Proc0 5 6 | 7 0 0 | 8 8491 ------------------------------- 8492 Proc1 18 0 | 19 20 21 | 0 8493 ------------------------------- 8494 Proc2 26 27 | 0 0 28 | 29 8495 0 0 | 31 32 33 | 0 8496 .ve 8497 8498 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8499 @*/ 8500 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8501 { 8502 PetscMPIInt size; 8503 Mat *local; 8504 IS iscoltmp; 8505 PetscBool flg; 8506 8507 PetscFunctionBegin; 8508 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8509 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8510 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8511 PetscAssertPointer(newmat, 5); 8512 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8513 PetscValidType(mat, 1); 8514 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8515 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8516 PetscCheck(cll != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_INPLACE_MATRIX"); 8517 8518 MatCheckPreallocated(mat, 1); 8519 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8520 8521 if (!iscol || isrow == iscol) { 8522 PetscBool stride; 8523 PetscMPIInt grabentirematrix = 0, grab; 8524 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8525 if (stride) { 8526 PetscInt first, step, n, rstart, rend; 8527 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8528 if (step == 1) { 8529 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8530 if (rstart == first) { 8531 PetscCall(ISGetLocalSize(isrow, &n)); 8532 if (n == rend - rstart) grabentirematrix = 1; 8533 } 8534 } 8535 } 8536 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8537 if (grab) { 8538 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8539 if (cll == MAT_INITIAL_MATRIX) { 8540 *newmat = mat; 8541 PetscCall(PetscObjectReference((PetscObject)mat)); 8542 } 8543 PetscFunctionReturn(PETSC_SUCCESS); 8544 } 8545 } 8546 8547 if (!iscol) { 8548 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8549 } else { 8550 iscoltmp = iscol; 8551 } 8552 8553 /* if original matrix is on just one processor then use submatrix generated */ 8554 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8555 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8556 goto setproperties; 8557 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8558 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8559 *newmat = *local; 8560 PetscCall(PetscFree(local)); 8561 goto setproperties; 8562 } else if (!mat->ops->createsubmatrix) { 8563 /* Create a new matrix type that implements the operation using the full matrix */ 8564 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8565 switch (cll) { 8566 case MAT_INITIAL_MATRIX: 8567 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8568 break; 8569 case MAT_REUSE_MATRIX: 8570 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8571 break; 8572 default: 8573 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8574 } 8575 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8576 goto setproperties; 8577 } 8578 8579 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8580 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8581 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8582 8583 setproperties: 8584 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8585 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8586 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8587 } 8588 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8589 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8590 if (!iscol || isrow == iscol) PetscCall(MatSelectVariableBlockSizes(*newmat, mat, isrow)); 8591 PetscFunctionReturn(PETSC_SUCCESS); 8592 } 8593 8594 /*@ 8595 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8596 8597 Not Collective 8598 8599 Input Parameters: 8600 + A - the matrix we wish to propagate options from 8601 - B - the matrix we wish to propagate options to 8602 8603 Level: beginner 8604 8605 Note: 8606 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8607 8608 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8609 @*/ 8610 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8611 { 8612 PetscFunctionBegin; 8613 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8614 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8615 B->symmetry_eternal = A->symmetry_eternal; 8616 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8617 B->symmetric = A->symmetric; 8618 B->structurally_symmetric = A->structurally_symmetric; 8619 B->spd = A->spd; 8620 B->hermitian = A->hermitian; 8621 PetscFunctionReturn(PETSC_SUCCESS); 8622 } 8623 8624 /*@ 8625 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8626 used during the assembly process to store values that belong to 8627 other processors. 8628 8629 Not Collective 8630 8631 Input Parameters: 8632 + mat - the matrix 8633 . size - the initial size of the stash. 8634 - bsize - the initial size of the block-stash(if used). 8635 8636 Options Database Keys: 8637 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8638 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8639 8640 Level: intermediate 8641 8642 Notes: 8643 The block-stash is used for values set with `MatSetValuesBlocked()` while 8644 the stash is used for values set with `MatSetValues()` 8645 8646 Run with the option -info and look for output of the form 8647 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8648 to determine the appropriate value, MM, to use for size and 8649 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8650 to determine the value, BMM to use for bsize 8651 8652 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8653 @*/ 8654 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8655 { 8656 PetscFunctionBegin; 8657 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8658 PetscValidType(mat, 1); 8659 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8660 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8661 PetscFunctionReturn(PETSC_SUCCESS); 8662 } 8663 8664 /*@ 8665 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8666 the matrix 8667 8668 Neighbor-wise Collective 8669 8670 Input Parameters: 8671 + A - the matrix 8672 . x - the vector to be multiplied by the interpolation operator 8673 - y - the vector to be added to the result 8674 8675 Output Parameter: 8676 . w - the resulting vector 8677 8678 Level: intermediate 8679 8680 Notes: 8681 `w` may be the same vector as `y`. 8682 8683 This allows one to use either the restriction or interpolation (its transpose) 8684 matrix to do the interpolation 8685 8686 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8687 @*/ 8688 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8689 { 8690 PetscInt M, N, Ny; 8691 8692 PetscFunctionBegin; 8693 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8694 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8695 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8696 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8697 PetscCall(MatGetSize(A, &M, &N)); 8698 PetscCall(VecGetSize(y, &Ny)); 8699 if (M == Ny) { 8700 PetscCall(MatMultAdd(A, x, y, w)); 8701 } else { 8702 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8703 } 8704 PetscFunctionReturn(PETSC_SUCCESS); 8705 } 8706 8707 /*@ 8708 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8709 the matrix 8710 8711 Neighbor-wise Collective 8712 8713 Input Parameters: 8714 + A - the matrix 8715 - x - the vector to be interpolated 8716 8717 Output Parameter: 8718 . y - the resulting vector 8719 8720 Level: intermediate 8721 8722 Note: 8723 This allows one to use either the restriction or interpolation (its transpose) 8724 matrix to do the interpolation 8725 8726 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8727 @*/ 8728 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8729 { 8730 PetscInt M, N, Ny; 8731 8732 PetscFunctionBegin; 8733 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8734 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8735 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8736 PetscCall(MatGetSize(A, &M, &N)); 8737 PetscCall(VecGetSize(y, &Ny)); 8738 if (M == Ny) { 8739 PetscCall(MatMult(A, x, y)); 8740 } else { 8741 PetscCall(MatMultTranspose(A, x, y)); 8742 } 8743 PetscFunctionReturn(PETSC_SUCCESS); 8744 } 8745 8746 /*@ 8747 MatRestrict - $y = A*x$ or $A^T*x$ 8748 8749 Neighbor-wise Collective 8750 8751 Input Parameters: 8752 + A - the matrix 8753 - x - the vector to be restricted 8754 8755 Output Parameter: 8756 . y - the resulting vector 8757 8758 Level: intermediate 8759 8760 Note: 8761 This allows one to use either the restriction or interpolation (its transpose) 8762 matrix to do the restriction 8763 8764 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8765 @*/ 8766 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8767 { 8768 PetscInt M, N, Nx; 8769 8770 PetscFunctionBegin; 8771 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8772 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8773 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8774 PetscCall(MatGetSize(A, &M, &N)); 8775 PetscCall(VecGetSize(x, &Nx)); 8776 if (M == Nx) { 8777 PetscCall(MatMultTranspose(A, x, y)); 8778 } else { 8779 PetscCall(MatMult(A, x, y)); 8780 } 8781 PetscFunctionReturn(PETSC_SUCCESS); 8782 } 8783 8784 /*@ 8785 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8786 8787 Neighbor-wise Collective 8788 8789 Input Parameters: 8790 + A - the matrix 8791 . x - the input dense matrix to be multiplied 8792 - w - the input dense matrix to be added to the result 8793 8794 Output Parameter: 8795 . y - the output dense matrix 8796 8797 Level: intermediate 8798 8799 Note: 8800 This allows one to use either the restriction or interpolation (its transpose) 8801 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8802 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8803 8804 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8805 @*/ 8806 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8807 { 8808 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8809 PetscBool trans = PETSC_TRUE; 8810 MatReuse reuse = MAT_INITIAL_MATRIX; 8811 8812 PetscFunctionBegin; 8813 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8814 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8815 PetscValidType(x, 2); 8816 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8817 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8818 PetscCall(MatGetSize(A, &M, &N)); 8819 PetscCall(MatGetSize(x, &Mx, &Nx)); 8820 if (N == Mx) trans = PETSC_FALSE; 8821 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); 8822 Mo = trans ? N : M; 8823 if (*y) { 8824 PetscCall(MatGetSize(*y, &My, &Ny)); 8825 if (Mo == My && Nx == Ny) { 8826 reuse = MAT_REUSE_MATRIX; 8827 } else { 8828 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); 8829 PetscCall(MatDestroy(y)); 8830 } 8831 } 8832 8833 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8834 PetscBool flg; 8835 8836 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8837 if (w) { 8838 PetscInt My, Ny, Mw, Nw; 8839 8840 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8841 PetscCall(MatGetSize(*y, &My, &Ny)); 8842 PetscCall(MatGetSize(w, &Mw, &Nw)); 8843 if (!flg || My != Mw || Ny != Nw) w = NULL; 8844 } 8845 if (!w) { 8846 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8847 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8848 PetscCall(PetscObjectDereference((PetscObject)w)); 8849 } else { 8850 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8851 } 8852 } 8853 if (!trans) { 8854 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8855 } else { 8856 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8857 } 8858 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8859 PetscFunctionReturn(PETSC_SUCCESS); 8860 } 8861 8862 /*@ 8863 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8864 8865 Neighbor-wise Collective 8866 8867 Input Parameters: 8868 + A - the matrix 8869 - x - the input dense matrix 8870 8871 Output Parameter: 8872 . y - the output dense matrix 8873 8874 Level: intermediate 8875 8876 Note: 8877 This allows one to use either the restriction or interpolation (its transpose) 8878 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8879 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8880 8881 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8882 @*/ 8883 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8884 { 8885 PetscFunctionBegin; 8886 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8887 PetscFunctionReturn(PETSC_SUCCESS); 8888 } 8889 8890 /*@ 8891 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8892 8893 Neighbor-wise Collective 8894 8895 Input Parameters: 8896 + A - the matrix 8897 - x - the input dense matrix 8898 8899 Output Parameter: 8900 . y - the output dense matrix 8901 8902 Level: intermediate 8903 8904 Note: 8905 This allows one to use either the restriction or interpolation (its transpose) 8906 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8907 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8908 8909 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8910 @*/ 8911 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8912 { 8913 PetscFunctionBegin; 8914 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8915 PetscFunctionReturn(PETSC_SUCCESS); 8916 } 8917 8918 /*@ 8919 MatGetNullSpace - retrieves the null space of a matrix. 8920 8921 Logically Collective 8922 8923 Input Parameters: 8924 + mat - the matrix 8925 - nullsp - the null space object 8926 8927 Level: developer 8928 8929 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8930 @*/ 8931 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8932 { 8933 PetscFunctionBegin; 8934 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8935 PetscAssertPointer(nullsp, 2); 8936 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8937 PetscFunctionReturn(PETSC_SUCCESS); 8938 } 8939 8940 /*@C 8941 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8942 8943 Logically Collective 8944 8945 Input Parameters: 8946 + n - the number of matrices 8947 - mat - the array of matrices 8948 8949 Output Parameters: 8950 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8951 8952 Level: developer 8953 8954 Note: 8955 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8956 8957 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8958 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8959 @*/ 8960 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8961 { 8962 PetscFunctionBegin; 8963 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8964 PetscAssertPointer(mat, 2); 8965 PetscAssertPointer(nullsp, 3); 8966 8967 PetscCall(PetscCalloc1(3 * n, nullsp)); 8968 for (PetscInt i = 0; i < n; i++) { 8969 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8970 (*nullsp)[i] = mat[i]->nullsp; 8971 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8972 (*nullsp)[n + i] = mat[i]->nearnullsp; 8973 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8974 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8975 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8976 } 8977 PetscFunctionReturn(PETSC_SUCCESS); 8978 } 8979 8980 /*@C 8981 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8982 8983 Logically Collective 8984 8985 Input Parameters: 8986 + n - the number of matrices 8987 . mat - the array of matrices 8988 - nullsp - an array of null spaces 8989 8990 Level: developer 8991 8992 Note: 8993 Call `MatGetNullSpaces()` to create `nullsp` 8994 8995 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8996 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8997 @*/ 8998 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8999 { 9000 PetscFunctionBegin; 9001 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 9002 PetscAssertPointer(mat, 2); 9003 PetscAssertPointer(nullsp, 3); 9004 PetscAssertPointer(*nullsp, 3); 9005 9006 for (PetscInt i = 0; i < n; i++) { 9007 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 9008 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 9009 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 9010 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 9011 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 9012 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 9013 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 9014 } 9015 PetscCall(PetscFree(*nullsp)); 9016 PetscFunctionReturn(PETSC_SUCCESS); 9017 } 9018 9019 /*@ 9020 MatSetNullSpace - attaches a null space to a matrix. 9021 9022 Logically Collective 9023 9024 Input Parameters: 9025 + mat - the matrix 9026 - nullsp - the null space object 9027 9028 Level: advanced 9029 9030 Notes: 9031 This null space is used by the `KSP` linear solvers to solve singular systems. 9032 9033 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` 9034 9035 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 9036 to zero but the linear system will still be solved in a least squares sense. 9037 9038 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 9039 the domain of a matrix $A$ (from $R^n$ to $R^m$ ($m$ rows, $n$ columns) $R^n$ = the direct sum of the null space of $A$, $n(A)$, plus the range of $A^T$, $R(A^T)$. 9040 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 9041 $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 9042 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)$. 9043 This $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9044 9045 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called 9046 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9047 routine also automatically calls `MatSetTransposeNullSpace()`. 9048 9049 The user should call `MatNullSpaceDestroy()`. 9050 9051 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9052 `KSPSetPCSide()` 9053 @*/ 9054 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9055 { 9056 PetscFunctionBegin; 9057 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9058 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9059 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9060 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9061 mat->nullsp = nullsp; 9062 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9063 PetscFunctionReturn(PETSC_SUCCESS); 9064 } 9065 9066 /*@ 9067 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9068 9069 Logically Collective 9070 9071 Input Parameters: 9072 + mat - the matrix 9073 - nullsp - the null space object 9074 9075 Level: developer 9076 9077 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9078 @*/ 9079 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9080 { 9081 PetscFunctionBegin; 9082 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9083 PetscValidType(mat, 1); 9084 PetscAssertPointer(nullsp, 2); 9085 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9086 PetscFunctionReturn(PETSC_SUCCESS); 9087 } 9088 9089 /*@ 9090 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9091 9092 Logically Collective 9093 9094 Input Parameters: 9095 + mat - the matrix 9096 - nullsp - the null space object 9097 9098 Level: advanced 9099 9100 Notes: 9101 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9102 9103 See `MatSetNullSpace()` 9104 9105 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9106 @*/ 9107 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9108 { 9109 PetscFunctionBegin; 9110 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9111 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9112 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9113 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9114 mat->transnullsp = nullsp; 9115 PetscFunctionReturn(PETSC_SUCCESS); 9116 } 9117 9118 /*@ 9119 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9120 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9121 9122 Logically Collective 9123 9124 Input Parameters: 9125 + mat - the matrix 9126 - nullsp - the null space object 9127 9128 Level: advanced 9129 9130 Notes: 9131 Overwrites any previous near null space that may have been attached 9132 9133 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9134 9135 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9136 @*/ 9137 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9138 { 9139 PetscFunctionBegin; 9140 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9141 PetscValidType(mat, 1); 9142 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9143 MatCheckPreallocated(mat, 1); 9144 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9145 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9146 mat->nearnullsp = nullsp; 9147 PetscFunctionReturn(PETSC_SUCCESS); 9148 } 9149 9150 /*@ 9151 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9152 9153 Not Collective 9154 9155 Input Parameter: 9156 . mat - the matrix 9157 9158 Output Parameter: 9159 . nullsp - the null space object, `NULL` if not set 9160 9161 Level: advanced 9162 9163 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9164 @*/ 9165 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9166 { 9167 PetscFunctionBegin; 9168 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9169 PetscValidType(mat, 1); 9170 PetscAssertPointer(nullsp, 2); 9171 MatCheckPreallocated(mat, 1); 9172 *nullsp = mat->nearnullsp; 9173 PetscFunctionReturn(PETSC_SUCCESS); 9174 } 9175 9176 /*@ 9177 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9178 9179 Collective 9180 9181 Input Parameters: 9182 + mat - the matrix 9183 . row - row/column permutation 9184 - info - information on desired factorization process 9185 9186 Level: developer 9187 9188 Notes: 9189 Probably really in-place only when level of fill is zero, otherwise allocates 9190 new space to store factored matrix and deletes previous memory. 9191 9192 Most users should employ the `KSP` interface for linear solvers 9193 instead of working directly with matrix algebra routines such as this. 9194 See, e.g., `KSPCreate()`. 9195 9196 Fortran Note: 9197 A valid (non-null) `info` argument must be provided 9198 9199 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9200 @*/ 9201 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9202 { 9203 PetscFunctionBegin; 9204 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9205 PetscValidType(mat, 1); 9206 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9207 PetscAssertPointer(info, 3); 9208 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9209 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9210 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9211 MatCheckPreallocated(mat, 1); 9212 PetscUseTypeMethod(mat, iccfactor, row, info); 9213 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9214 PetscFunctionReturn(PETSC_SUCCESS); 9215 } 9216 9217 /*@ 9218 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9219 ghosted ones. 9220 9221 Not Collective 9222 9223 Input Parameters: 9224 + mat - the matrix 9225 - diag - the diagonal values, including ghost ones 9226 9227 Level: developer 9228 9229 Notes: 9230 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9231 9232 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9233 9234 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9235 @*/ 9236 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9237 { 9238 PetscMPIInt size; 9239 9240 PetscFunctionBegin; 9241 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9242 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9243 PetscValidType(mat, 1); 9244 9245 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9246 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9247 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9248 if (size == 1) { 9249 PetscInt n, m; 9250 PetscCall(VecGetSize(diag, &n)); 9251 PetscCall(MatGetSize(mat, NULL, &m)); 9252 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9253 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9254 } else { 9255 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9256 } 9257 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9258 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9259 PetscFunctionReturn(PETSC_SUCCESS); 9260 } 9261 9262 /*@ 9263 MatGetInertia - Gets the inertia from a factored matrix 9264 9265 Collective 9266 9267 Input Parameter: 9268 . mat - the matrix 9269 9270 Output Parameters: 9271 + nneg - number of negative eigenvalues 9272 . nzero - number of zero eigenvalues 9273 - npos - number of positive eigenvalues 9274 9275 Level: advanced 9276 9277 Note: 9278 Matrix must have been factored by `MatCholeskyFactor()` 9279 9280 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9281 @*/ 9282 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9283 { 9284 PetscFunctionBegin; 9285 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9286 PetscValidType(mat, 1); 9287 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9288 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9289 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9290 PetscFunctionReturn(PETSC_SUCCESS); 9291 } 9292 9293 /*@C 9294 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9295 9296 Neighbor-wise Collective 9297 9298 Input Parameters: 9299 + mat - the factored matrix obtained with `MatGetFactor()` 9300 - b - the right-hand-side vectors 9301 9302 Output Parameter: 9303 . x - the result vectors 9304 9305 Level: developer 9306 9307 Note: 9308 The vectors `b` and `x` cannot be the same. I.e., one cannot 9309 call `MatSolves`(A,x,x). 9310 9311 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9312 @*/ 9313 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9314 { 9315 PetscFunctionBegin; 9316 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9317 PetscValidType(mat, 1); 9318 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9319 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9320 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9321 9322 MatCheckPreallocated(mat, 1); 9323 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9324 PetscUseTypeMethod(mat, solves, b, x); 9325 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9326 PetscFunctionReturn(PETSC_SUCCESS); 9327 } 9328 9329 /*@ 9330 MatIsSymmetric - Test whether a matrix is symmetric 9331 9332 Collective 9333 9334 Input Parameters: 9335 + A - the matrix to test 9336 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9337 9338 Output Parameter: 9339 . flg - the result 9340 9341 Level: intermediate 9342 9343 Notes: 9344 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9345 9346 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9347 9348 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9349 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9350 9351 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9352 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9353 @*/ 9354 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9355 { 9356 PetscFunctionBegin; 9357 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9358 PetscAssertPointer(flg, 3); 9359 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9360 else { 9361 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9362 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9363 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9364 } 9365 PetscFunctionReturn(PETSC_SUCCESS); 9366 } 9367 9368 /*@ 9369 MatIsHermitian - Test whether a matrix is Hermitian 9370 9371 Collective 9372 9373 Input Parameters: 9374 + A - the matrix to test 9375 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9376 9377 Output Parameter: 9378 . flg - the result 9379 9380 Level: intermediate 9381 9382 Notes: 9383 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9384 9385 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9386 9387 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9388 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9389 9390 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9391 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9392 @*/ 9393 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9394 { 9395 PetscFunctionBegin; 9396 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9397 PetscAssertPointer(flg, 3); 9398 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9399 else { 9400 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9401 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9402 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9403 } 9404 PetscFunctionReturn(PETSC_SUCCESS); 9405 } 9406 9407 /*@ 9408 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9409 9410 Not Collective 9411 9412 Input Parameter: 9413 . A - the matrix to check 9414 9415 Output Parameters: 9416 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9417 - flg - the result (only valid if set is `PETSC_TRUE`) 9418 9419 Level: advanced 9420 9421 Notes: 9422 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9423 if you want it explicitly checked 9424 9425 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9426 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9427 9428 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9429 @*/ 9430 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9431 { 9432 PetscFunctionBegin; 9433 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9434 PetscAssertPointer(set, 2); 9435 PetscAssertPointer(flg, 3); 9436 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9437 *set = PETSC_TRUE; 9438 *flg = PetscBool3ToBool(A->symmetric); 9439 } else { 9440 *set = PETSC_FALSE; 9441 } 9442 PetscFunctionReturn(PETSC_SUCCESS); 9443 } 9444 9445 /*@ 9446 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9447 9448 Not Collective 9449 9450 Input Parameter: 9451 . A - the matrix to check 9452 9453 Output Parameters: 9454 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9455 - flg - the result (only valid if set is `PETSC_TRUE`) 9456 9457 Level: advanced 9458 9459 Notes: 9460 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9461 9462 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9463 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9464 9465 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9466 @*/ 9467 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9468 { 9469 PetscFunctionBegin; 9470 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9471 PetscAssertPointer(set, 2); 9472 PetscAssertPointer(flg, 3); 9473 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9474 *set = PETSC_TRUE; 9475 *flg = PetscBool3ToBool(A->spd); 9476 } else { 9477 *set = PETSC_FALSE; 9478 } 9479 PetscFunctionReturn(PETSC_SUCCESS); 9480 } 9481 9482 /*@ 9483 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9484 9485 Not Collective 9486 9487 Input Parameter: 9488 . A - the matrix to check 9489 9490 Output Parameters: 9491 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9492 - flg - the result (only valid if set is `PETSC_TRUE`) 9493 9494 Level: advanced 9495 9496 Notes: 9497 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9498 if you want it explicitly checked 9499 9500 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9501 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9502 9503 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9504 @*/ 9505 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9506 { 9507 PetscFunctionBegin; 9508 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9509 PetscAssertPointer(set, 2); 9510 PetscAssertPointer(flg, 3); 9511 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9512 *set = PETSC_TRUE; 9513 *flg = PetscBool3ToBool(A->hermitian); 9514 } else { 9515 *set = PETSC_FALSE; 9516 } 9517 PetscFunctionReturn(PETSC_SUCCESS); 9518 } 9519 9520 /*@ 9521 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9522 9523 Collective 9524 9525 Input Parameter: 9526 . A - the matrix to test 9527 9528 Output Parameter: 9529 . flg - the result 9530 9531 Level: intermediate 9532 9533 Notes: 9534 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9535 9536 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 9537 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9538 9539 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9540 @*/ 9541 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9542 { 9543 PetscFunctionBegin; 9544 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9545 PetscAssertPointer(flg, 2); 9546 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9547 *flg = PetscBool3ToBool(A->structurally_symmetric); 9548 } else { 9549 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9550 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9551 } 9552 PetscFunctionReturn(PETSC_SUCCESS); 9553 } 9554 9555 /*@ 9556 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9557 9558 Not Collective 9559 9560 Input Parameter: 9561 . A - the matrix to check 9562 9563 Output Parameters: 9564 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9565 - flg - the result (only valid if set is PETSC_TRUE) 9566 9567 Level: advanced 9568 9569 Notes: 9570 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 9571 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9572 9573 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9574 9575 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9576 @*/ 9577 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9578 { 9579 PetscFunctionBegin; 9580 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9581 PetscAssertPointer(set, 2); 9582 PetscAssertPointer(flg, 3); 9583 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9584 *set = PETSC_TRUE; 9585 *flg = PetscBool3ToBool(A->structurally_symmetric); 9586 } else { 9587 *set = PETSC_FALSE; 9588 } 9589 PetscFunctionReturn(PETSC_SUCCESS); 9590 } 9591 9592 /*@ 9593 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9594 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9595 9596 Not Collective 9597 9598 Input Parameter: 9599 . mat - the matrix 9600 9601 Output Parameters: 9602 + nstash - the size of the stash 9603 . reallocs - the number of additional mallocs incurred. 9604 . bnstash - the size of the block stash 9605 - breallocs - the number of additional mallocs incurred.in the block stash 9606 9607 Level: advanced 9608 9609 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9610 @*/ 9611 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9612 { 9613 PetscFunctionBegin; 9614 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9615 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9616 PetscFunctionReturn(PETSC_SUCCESS); 9617 } 9618 9619 /*@ 9620 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9621 parallel layout, `PetscLayout` for rows and columns 9622 9623 Collective 9624 9625 Input Parameter: 9626 . mat - the matrix 9627 9628 Output Parameters: 9629 + right - (optional) vector that the matrix can be multiplied against 9630 - left - (optional) vector that the matrix vector product can be stored in 9631 9632 Level: advanced 9633 9634 Notes: 9635 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()`. 9636 9637 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9638 9639 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9640 @*/ 9641 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9642 { 9643 PetscFunctionBegin; 9644 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9645 PetscValidType(mat, 1); 9646 if (mat->ops->getvecs) { 9647 PetscUseTypeMethod(mat, getvecs, right, left); 9648 } else { 9649 if (right) { 9650 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9651 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9652 PetscCall(VecSetType(*right, mat->defaultvectype)); 9653 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9654 if (mat->boundtocpu && mat->bindingpropagates) { 9655 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9656 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9657 } 9658 #endif 9659 } 9660 if (left) { 9661 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9662 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9663 PetscCall(VecSetType(*left, mat->defaultvectype)); 9664 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9665 if (mat->boundtocpu && mat->bindingpropagates) { 9666 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9667 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9668 } 9669 #endif 9670 } 9671 } 9672 PetscFunctionReturn(PETSC_SUCCESS); 9673 } 9674 9675 /*@ 9676 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9677 with default values. 9678 9679 Not Collective 9680 9681 Input Parameter: 9682 . info - the `MatFactorInfo` data structure 9683 9684 Level: developer 9685 9686 Notes: 9687 The solvers are generally used through the `KSP` and `PC` objects, for example 9688 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9689 9690 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9691 9692 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9693 @*/ 9694 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9695 { 9696 PetscFunctionBegin; 9697 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9698 PetscFunctionReturn(PETSC_SUCCESS); 9699 } 9700 9701 /*@ 9702 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9703 9704 Collective 9705 9706 Input Parameters: 9707 + mat - the factored matrix 9708 - is - the index set defining the Schur indices (0-based) 9709 9710 Level: advanced 9711 9712 Notes: 9713 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9714 9715 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9716 9717 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9718 9719 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9720 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9721 @*/ 9722 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9723 { 9724 PetscErrorCode (*f)(Mat, IS); 9725 9726 PetscFunctionBegin; 9727 PetscValidType(mat, 1); 9728 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9729 PetscValidType(is, 2); 9730 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9731 PetscCheckSameComm(mat, 1, is, 2); 9732 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9733 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9734 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9735 PetscCall(MatDestroy(&mat->schur)); 9736 PetscCall((*f)(mat, is)); 9737 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9738 PetscFunctionReturn(PETSC_SUCCESS); 9739 } 9740 9741 /*@ 9742 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9743 9744 Logically Collective 9745 9746 Input Parameters: 9747 + F - the factored matrix obtained by calling `MatGetFactor()` 9748 . S - location where to return the Schur complement, can be `NULL` 9749 - status - the status of the Schur complement matrix, can be `NULL` 9750 9751 Level: advanced 9752 9753 Notes: 9754 You must call `MatFactorSetSchurIS()` before calling this routine. 9755 9756 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9757 9758 The routine provides a copy of the Schur matrix stored within the solver data structures. 9759 The caller must destroy the object when it is no longer needed. 9760 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9761 9762 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) 9763 9764 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9765 9766 Developer Note: 9767 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9768 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9769 9770 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9771 @*/ 9772 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9773 { 9774 PetscFunctionBegin; 9775 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9776 if (S) PetscAssertPointer(S, 2); 9777 if (status) PetscAssertPointer(status, 3); 9778 if (S) { 9779 PetscErrorCode (*f)(Mat, Mat *); 9780 9781 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9782 if (f) { 9783 PetscCall((*f)(F, S)); 9784 } else { 9785 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9786 } 9787 } 9788 if (status) *status = F->schur_status; 9789 PetscFunctionReturn(PETSC_SUCCESS); 9790 } 9791 9792 /*@ 9793 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9794 9795 Logically Collective 9796 9797 Input Parameters: 9798 + F - the factored matrix obtained by calling `MatGetFactor()` 9799 . S - location where to return the Schur complement, can be `NULL` 9800 - status - the status of the Schur complement matrix, can be `NULL` 9801 9802 Level: advanced 9803 9804 Notes: 9805 You must call `MatFactorSetSchurIS()` before calling this routine. 9806 9807 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9808 9809 The routine returns a the Schur Complement stored within the data structures of the solver. 9810 9811 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9812 9813 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9814 9815 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9816 9817 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9818 9819 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9820 @*/ 9821 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9822 { 9823 PetscFunctionBegin; 9824 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9825 if (S) { 9826 PetscAssertPointer(S, 2); 9827 *S = F->schur; 9828 } 9829 if (status) { 9830 PetscAssertPointer(status, 3); 9831 *status = F->schur_status; 9832 } 9833 PetscFunctionReturn(PETSC_SUCCESS); 9834 } 9835 9836 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9837 { 9838 Mat S = F->schur; 9839 9840 PetscFunctionBegin; 9841 switch (F->schur_status) { 9842 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9843 case MAT_FACTOR_SCHUR_INVERTED: 9844 if (S) { 9845 S->ops->solve = NULL; 9846 S->ops->matsolve = NULL; 9847 S->ops->solvetranspose = NULL; 9848 S->ops->matsolvetranspose = NULL; 9849 S->ops->solveadd = NULL; 9850 S->ops->solvetransposeadd = NULL; 9851 S->factortype = MAT_FACTOR_NONE; 9852 PetscCall(PetscFree(S->solvertype)); 9853 } 9854 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9855 break; 9856 default: 9857 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9858 } 9859 PetscFunctionReturn(PETSC_SUCCESS); 9860 } 9861 9862 /*@ 9863 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9864 9865 Logically Collective 9866 9867 Input Parameters: 9868 + F - the factored matrix obtained by calling `MatGetFactor()` 9869 . S - location where the Schur complement is stored 9870 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9871 9872 Level: advanced 9873 9874 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9875 @*/ 9876 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9877 { 9878 PetscFunctionBegin; 9879 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9880 if (S) { 9881 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9882 *S = NULL; 9883 } 9884 F->schur_status = status; 9885 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9886 PetscFunctionReturn(PETSC_SUCCESS); 9887 } 9888 9889 /*@ 9890 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9891 9892 Logically Collective 9893 9894 Input Parameters: 9895 + F - the factored matrix obtained by calling `MatGetFactor()` 9896 . rhs - location where the right-hand side of the Schur complement system is stored 9897 - sol - location where the solution of the Schur complement system has to be returned 9898 9899 Level: advanced 9900 9901 Notes: 9902 The sizes of the vectors should match the size of the Schur complement 9903 9904 Must be called after `MatFactorSetSchurIS()` 9905 9906 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9907 @*/ 9908 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9909 { 9910 PetscFunctionBegin; 9911 PetscValidType(F, 1); 9912 PetscValidType(rhs, 2); 9913 PetscValidType(sol, 3); 9914 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9915 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9916 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9917 PetscCheckSameComm(F, 1, rhs, 2); 9918 PetscCheckSameComm(F, 1, sol, 3); 9919 PetscCall(MatFactorFactorizeSchurComplement(F)); 9920 switch (F->schur_status) { 9921 case MAT_FACTOR_SCHUR_FACTORED: 9922 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9923 break; 9924 case MAT_FACTOR_SCHUR_INVERTED: 9925 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9926 break; 9927 default: 9928 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9929 } 9930 PetscFunctionReturn(PETSC_SUCCESS); 9931 } 9932 9933 /*@ 9934 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9935 9936 Logically Collective 9937 9938 Input Parameters: 9939 + F - the factored matrix obtained by calling `MatGetFactor()` 9940 . rhs - location where the right-hand side of the Schur complement system is stored 9941 - sol - location where the solution of the Schur complement system has to be returned 9942 9943 Level: advanced 9944 9945 Notes: 9946 The sizes of the vectors should match the size of the Schur complement 9947 9948 Must be called after `MatFactorSetSchurIS()` 9949 9950 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9951 @*/ 9952 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9953 { 9954 PetscFunctionBegin; 9955 PetscValidType(F, 1); 9956 PetscValidType(rhs, 2); 9957 PetscValidType(sol, 3); 9958 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9959 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9960 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9961 PetscCheckSameComm(F, 1, rhs, 2); 9962 PetscCheckSameComm(F, 1, sol, 3); 9963 PetscCall(MatFactorFactorizeSchurComplement(F)); 9964 switch (F->schur_status) { 9965 case MAT_FACTOR_SCHUR_FACTORED: 9966 PetscCall(MatSolve(F->schur, rhs, sol)); 9967 break; 9968 case MAT_FACTOR_SCHUR_INVERTED: 9969 PetscCall(MatMult(F->schur, rhs, sol)); 9970 break; 9971 default: 9972 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9973 } 9974 PetscFunctionReturn(PETSC_SUCCESS); 9975 } 9976 9977 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9978 #if PetscDefined(HAVE_CUDA) 9979 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9980 #endif 9981 9982 /* Schur status updated in the interface */ 9983 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9984 { 9985 Mat S = F->schur; 9986 9987 PetscFunctionBegin; 9988 if (S) { 9989 PetscMPIInt size; 9990 PetscBool isdense, isdensecuda; 9991 9992 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9993 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9994 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9995 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9996 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9997 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9998 if (isdense) { 9999 PetscCall(MatSeqDenseInvertFactors_Private(S)); 10000 } else if (isdensecuda) { 10001 #if defined(PETSC_HAVE_CUDA) 10002 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 10003 #endif 10004 } 10005 // HIP?????????????? 10006 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 10007 } 10008 PetscFunctionReturn(PETSC_SUCCESS); 10009 } 10010 10011 /*@ 10012 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 10013 10014 Logically Collective 10015 10016 Input Parameter: 10017 . F - the factored matrix obtained by calling `MatGetFactor()` 10018 10019 Level: advanced 10020 10021 Notes: 10022 Must be called after `MatFactorSetSchurIS()`. 10023 10024 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 10025 10026 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 10027 @*/ 10028 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 10029 { 10030 PetscFunctionBegin; 10031 PetscValidType(F, 1); 10032 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10033 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 10034 PetscCall(MatFactorFactorizeSchurComplement(F)); 10035 PetscCall(MatFactorInvertSchurComplement_Private(F)); 10036 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 10037 PetscFunctionReturn(PETSC_SUCCESS); 10038 } 10039 10040 /*@ 10041 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10042 10043 Logically Collective 10044 10045 Input Parameter: 10046 . F - the factored matrix obtained by calling `MatGetFactor()` 10047 10048 Level: advanced 10049 10050 Note: 10051 Must be called after `MatFactorSetSchurIS()` 10052 10053 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10054 @*/ 10055 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10056 { 10057 MatFactorInfo info; 10058 10059 PetscFunctionBegin; 10060 PetscValidType(F, 1); 10061 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10062 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10063 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10064 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10065 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10066 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10067 } else { 10068 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10069 } 10070 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10071 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10072 PetscFunctionReturn(PETSC_SUCCESS); 10073 } 10074 10075 /*@ 10076 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10077 10078 Neighbor-wise Collective 10079 10080 Input Parameters: 10081 + A - the matrix 10082 . P - the projection matrix 10083 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10084 - 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 10085 if the result is a dense matrix this is irrelevant 10086 10087 Output Parameter: 10088 . C - the product matrix 10089 10090 Level: intermediate 10091 10092 Notes: 10093 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10094 10095 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_PtAP` 10096 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10097 10098 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10099 10100 Developer Note: 10101 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10102 10103 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10104 @*/ 10105 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10106 { 10107 PetscFunctionBegin; 10108 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10109 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10110 10111 if (scall == MAT_INITIAL_MATRIX) { 10112 PetscCall(MatProductCreate(A, P, NULL, C)); 10113 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10114 PetscCall(MatProductSetAlgorithm(*C, "default")); 10115 PetscCall(MatProductSetFill(*C, fill)); 10116 10117 (*C)->product->api_user = PETSC_TRUE; 10118 PetscCall(MatProductSetFromOptions(*C)); 10119 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); 10120 PetscCall(MatProductSymbolic(*C)); 10121 } else { /* scall == MAT_REUSE_MATRIX */ 10122 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10123 } 10124 10125 PetscCall(MatProductNumeric(*C)); 10126 if (A->symmetric == PETSC_BOOL3_TRUE) { 10127 PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10128 (*C)->spd = A->spd; 10129 } 10130 PetscFunctionReturn(PETSC_SUCCESS); 10131 } 10132 10133 /*@ 10134 MatRARt - Creates the matrix product $C = R * A * R^T$ 10135 10136 Neighbor-wise Collective 10137 10138 Input Parameters: 10139 + A - the matrix 10140 . R - the projection matrix 10141 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10142 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10143 if the result is a dense matrix this is irrelevant 10144 10145 Output Parameter: 10146 . C - the product matrix 10147 10148 Level: intermediate 10149 10150 Notes: 10151 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10152 10153 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_RARt` 10154 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10155 10156 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10157 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10158 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10159 We recommend using `MatPtAP()` when possible. 10160 10161 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10162 10163 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10164 @*/ 10165 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10166 { 10167 PetscFunctionBegin; 10168 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10169 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10170 10171 if (scall == MAT_INITIAL_MATRIX) { 10172 PetscCall(MatProductCreate(A, R, NULL, C)); 10173 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10174 PetscCall(MatProductSetAlgorithm(*C, "default")); 10175 PetscCall(MatProductSetFill(*C, fill)); 10176 10177 (*C)->product->api_user = PETSC_TRUE; 10178 PetscCall(MatProductSetFromOptions(*C)); 10179 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); 10180 PetscCall(MatProductSymbolic(*C)); 10181 } else { /* scall == MAT_REUSE_MATRIX */ 10182 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10183 } 10184 10185 PetscCall(MatProductNumeric(*C)); 10186 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10187 PetscFunctionReturn(PETSC_SUCCESS); 10188 } 10189 10190 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10191 { 10192 PetscBool flg = PETSC_TRUE; 10193 10194 PetscFunctionBegin; 10195 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10196 if (scall == MAT_INITIAL_MATRIX) { 10197 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10198 PetscCall(MatProductCreate(A, B, NULL, C)); 10199 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10200 PetscCall(MatProductSetFill(*C, fill)); 10201 } else { /* scall == MAT_REUSE_MATRIX */ 10202 Mat_Product *product = (*C)->product; 10203 10204 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10205 if (flg && product && product->type != ptype) { 10206 PetscCall(MatProductClear(*C)); 10207 product = NULL; 10208 } 10209 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10210 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10211 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10212 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10213 product = (*C)->product; 10214 product->fill = fill; 10215 product->clear = PETSC_TRUE; 10216 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10217 flg = PETSC_FALSE; 10218 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10219 } 10220 } 10221 if (flg) { 10222 (*C)->product->api_user = PETSC_TRUE; 10223 PetscCall(MatProductSetType(*C, ptype)); 10224 PetscCall(MatProductSetFromOptions(*C)); 10225 PetscCall(MatProductSymbolic(*C)); 10226 } 10227 PetscCall(MatProductNumeric(*C)); 10228 PetscFunctionReturn(PETSC_SUCCESS); 10229 } 10230 10231 /*@ 10232 MatMatMult - Performs matrix-matrix multiplication $ C=A*B $. 10233 10234 Neighbor-wise Collective 10235 10236 Input Parameters: 10237 + A - the left matrix 10238 . B - the right matrix 10239 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10240 - 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 10241 if the result is a dense matrix this is irrelevant 10242 10243 Output Parameter: 10244 . C - the product matrix 10245 10246 Notes: 10247 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10248 10249 `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 10250 call to this function with `MAT_INITIAL_MATRIX`. 10251 10252 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10253 10254 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`, 10255 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10256 10257 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10258 10259 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_AB` 10260 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10261 10262 Example of Usage: 10263 .vb 10264 MatProductCreate(A,B,NULL,&C); 10265 MatProductSetType(C,MATPRODUCT_AB); 10266 MatProductSymbolic(C); 10267 MatProductNumeric(C); // compute C=A * B 10268 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10269 MatProductNumeric(C); 10270 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10271 MatProductNumeric(C); 10272 .ve 10273 10274 Level: intermediate 10275 10276 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10277 @*/ 10278 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10279 { 10280 PetscFunctionBegin; 10281 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10282 PetscFunctionReturn(PETSC_SUCCESS); 10283 } 10284 10285 /*@ 10286 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10287 10288 Neighbor-wise Collective 10289 10290 Input Parameters: 10291 + A - the left matrix 10292 . B - the right matrix 10293 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10294 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10295 10296 Output Parameter: 10297 . C - the product matrix 10298 10299 Options Database Key: 10300 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10301 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10302 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10303 10304 Level: intermediate 10305 10306 Notes: 10307 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10308 10309 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10310 10311 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10312 actually needed. 10313 10314 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10315 and for pairs of `MATMPIDENSE` matrices. 10316 10317 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_ABt` 10318 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10319 10320 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10321 10322 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10323 @*/ 10324 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10325 { 10326 PetscFunctionBegin; 10327 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10328 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10329 PetscFunctionReturn(PETSC_SUCCESS); 10330 } 10331 10332 /*@ 10333 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10334 10335 Neighbor-wise Collective 10336 10337 Input Parameters: 10338 + A - the left matrix 10339 . B - the right matrix 10340 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10341 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10342 10343 Output Parameter: 10344 . C - the product matrix 10345 10346 Level: intermediate 10347 10348 Notes: 10349 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10350 10351 `MAT_REUSE_MATRIX` can only be used if `A` and `B` have the same nonzero pattern as in the previous call. 10352 10353 This is a convenience routine that wraps the use of `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_AtB` 10354 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10355 10356 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10357 actually needed. 10358 10359 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10360 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10361 10362 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10363 10364 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10365 @*/ 10366 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10367 { 10368 PetscFunctionBegin; 10369 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10370 PetscFunctionReturn(PETSC_SUCCESS); 10371 } 10372 10373 /*@ 10374 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10375 10376 Neighbor-wise Collective 10377 10378 Input Parameters: 10379 + A - the left matrix 10380 . B - the middle matrix 10381 . C - the right matrix 10382 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10383 - 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 10384 if the result is a dense matrix this is irrelevant 10385 10386 Output Parameter: 10387 . D - the product matrix 10388 10389 Level: intermediate 10390 10391 Notes: 10392 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10393 10394 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10395 10396 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_ABC` 10397 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10398 10399 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value 10400 actually needed. 10401 10402 If you have many matrices with the same non-zero structure to multiply, you 10403 should use `MAT_REUSE_MATRIX` in all calls but the first 10404 10405 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10406 10407 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10408 @*/ 10409 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10410 { 10411 PetscFunctionBegin; 10412 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10413 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10414 10415 if (scall == MAT_INITIAL_MATRIX) { 10416 PetscCall(MatProductCreate(A, B, C, D)); 10417 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10418 PetscCall(MatProductSetAlgorithm(*D, "default")); 10419 PetscCall(MatProductSetFill(*D, fill)); 10420 10421 (*D)->product->api_user = PETSC_TRUE; 10422 PetscCall(MatProductSetFromOptions(*D)); 10423 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, 10424 ((PetscObject)C)->type_name); 10425 PetscCall(MatProductSymbolic(*D)); 10426 } else { /* user may change input matrices when REUSE */ 10427 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10428 } 10429 PetscCall(MatProductNumeric(*D)); 10430 PetscFunctionReturn(PETSC_SUCCESS); 10431 } 10432 10433 /*@ 10434 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10435 10436 Collective 10437 10438 Input Parameters: 10439 + mat - the matrix 10440 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10441 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10442 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10443 10444 Output Parameter: 10445 . matredundant - redundant matrix 10446 10447 Level: advanced 10448 10449 Notes: 10450 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10451 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10452 10453 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10454 calling it. 10455 10456 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10457 10458 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10459 @*/ 10460 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10461 { 10462 MPI_Comm comm; 10463 PetscMPIInt size; 10464 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10465 Mat_Redundant *redund = NULL; 10466 PetscSubcomm psubcomm = NULL; 10467 MPI_Comm subcomm_in = subcomm; 10468 Mat *matseq; 10469 IS isrow, iscol; 10470 PetscBool newsubcomm = PETSC_FALSE; 10471 10472 PetscFunctionBegin; 10473 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10474 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10475 PetscAssertPointer(*matredundant, 5); 10476 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10477 } 10478 10479 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10480 if (size == 1 || nsubcomm == 1) { 10481 if (reuse == MAT_INITIAL_MATRIX) { 10482 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10483 } else { 10484 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"); 10485 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10486 } 10487 PetscFunctionReturn(PETSC_SUCCESS); 10488 } 10489 10490 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10491 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10492 MatCheckPreallocated(mat, 1); 10493 10494 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10495 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10496 /* create psubcomm, then get subcomm */ 10497 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10498 PetscCallMPI(MPI_Comm_size(comm, &size)); 10499 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10500 10501 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10502 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10503 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10504 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10505 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10506 newsubcomm = PETSC_TRUE; 10507 PetscCall(PetscSubcommDestroy(&psubcomm)); 10508 } 10509 10510 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10511 if (reuse == MAT_INITIAL_MATRIX) { 10512 mloc_sub = PETSC_DECIDE; 10513 nloc_sub = PETSC_DECIDE; 10514 if (bs < 1) { 10515 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10516 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10517 } else { 10518 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10519 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10520 } 10521 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10522 rstart = rend - mloc_sub; 10523 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10524 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10525 PetscCall(ISSetIdentity(iscol)); 10526 } else { /* reuse == MAT_REUSE_MATRIX */ 10527 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"); 10528 /* retrieve subcomm */ 10529 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10530 redund = (*matredundant)->redundant; 10531 isrow = redund->isrow; 10532 iscol = redund->iscol; 10533 matseq = redund->matseq; 10534 } 10535 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10536 10537 /* get matredundant over subcomm */ 10538 if (reuse == MAT_INITIAL_MATRIX) { 10539 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10540 10541 /* create a supporting struct and attach it to C for reuse */ 10542 PetscCall(PetscNew(&redund)); 10543 (*matredundant)->redundant = redund; 10544 redund->isrow = isrow; 10545 redund->iscol = iscol; 10546 redund->matseq = matseq; 10547 if (newsubcomm) { 10548 redund->subcomm = subcomm; 10549 } else { 10550 redund->subcomm = MPI_COMM_NULL; 10551 } 10552 } else { 10553 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10554 } 10555 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10556 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10557 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10558 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10559 } 10560 #endif 10561 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10562 PetscFunctionReturn(PETSC_SUCCESS); 10563 } 10564 10565 /*@C 10566 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10567 a given `Mat`. Each submatrix can span multiple procs. 10568 10569 Collective 10570 10571 Input Parameters: 10572 + mat - the matrix 10573 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10574 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10575 10576 Output Parameter: 10577 . subMat - parallel sub-matrices each spanning a given `subcomm` 10578 10579 Level: advanced 10580 10581 Notes: 10582 The submatrix partition across processors is dictated by `subComm` a 10583 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10584 is not restricted to be grouped with consecutive original MPI processes. 10585 10586 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10587 map directly to the layout of the original matrix [wrt the local 10588 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10589 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10590 the `subMat`. However the offDiagMat looses some columns - and this is 10591 reconstructed with `MatSetValues()` 10592 10593 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10594 10595 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10596 @*/ 10597 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10598 { 10599 PetscMPIInt commsize, subCommSize; 10600 10601 PetscFunctionBegin; 10602 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10603 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10604 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10605 10606 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"); 10607 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10608 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10609 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10610 PetscFunctionReturn(PETSC_SUCCESS); 10611 } 10612 10613 /*@ 10614 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10615 10616 Not Collective 10617 10618 Input Parameters: 10619 + mat - matrix to extract local submatrix from 10620 . isrow - local row indices for submatrix 10621 - iscol - local column indices for submatrix 10622 10623 Output Parameter: 10624 . submat - the submatrix 10625 10626 Level: intermediate 10627 10628 Notes: 10629 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10630 10631 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10632 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10633 10634 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10635 `MatSetValuesBlockedLocal()` will also be implemented. 10636 10637 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10638 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10639 10640 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10641 @*/ 10642 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10643 { 10644 PetscFunctionBegin; 10645 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10646 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10647 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10648 PetscCheckSameComm(isrow, 2, iscol, 3); 10649 PetscAssertPointer(submat, 4); 10650 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10651 10652 if (mat->ops->getlocalsubmatrix) { 10653 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10654 } else { 10655 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10656 } 10657 (*submat)->assembled = mat->assembled; 10658 PetscFunctionReturn(PETSC_SUCCESS); 10659 } 10660 10661 /*@ 10662 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10663 10664 Not Collective 10665 10666 Input Parameters: 10667 + mat - matrix to extract local submatrix from 10668 . isrow - local row indices for submatrix 10669 . iscol - local column indices for submatrix 10670 - submat - the submatrix 10671 10672 Level: intermediate 10673 10674 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10675 @*/ 10676 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10677 { 10678 PetscFunctionBegin; 10679 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10680 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10681 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10682 PetscCheckSameComm(isrow, 2, iscol, 3); 10683 PetscAssertPointer(submat, 4); 10684 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10685 10686 if (mat->ops->restorelocalsubmatrix) { 10687 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10688 } else { 10689 PetscCall(MatDestroy(submat)); 10690 } 10691 *submat = NULL; 10692 PetscFunctionReturn(PETSC_SUCCESS); 10693 } 10694 10695 /*@ 10696 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10697 10698 Collective 10699 10700 Input Parameter: 10701 . mat - the matrix 10702 10703 Output Parameter: 10704 . is - if any rows have zero diagonals this contains the list of them 10705 10706 Level: developer 10707 10708 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10709 @*/ 10710 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10711 { 10712 PetscFunctionBegin; 10713 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10714 PetscValidType(mat, 1); 10715 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10716 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10717 10718 if (!mat->ops->findzerodiagonals) { 10719 Vec diag; 10720 const PetscScalar *a; 10721 PetscInt *rows; 10722 PetscInt rStart, rEnd, r, nrow = 0; 10723 10724 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10725 PetscCall(MatGetDiagonal(mat, diag)); 10726 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10727 PetscCall(VecGetArrayRead(diag, &a)); 10728 for (r = 0; r < rEnd - rStart; ++r) 10729 if (a[r] == 0.0) ++nrow; 10730 PetscCall(PetscMalloc1(nrow, &rows)); 10731 nrow = 0; 10732 for (r = 0; r < rEnd - rStart; ++r) 10733 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10734 PetscCall(VecRestoreArrayRead(diag, &a)); 10735 PetscCall(VecDestroy(&diag)); 10736 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10737 } else { 10738 PetscUseTypeMethod(mat, findzerodiagonals, is); 10739 } 10740 PetscFunctionReturn(PETSC_SUCCESS); 10741 } 10742 10743 /*@ 10744 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10745 10746 Collective 10747 10748 Input Parameter: 10749 . mat - the matrix 10750 10751 Output Parameter: 10752 . is - contains the list of rows with off block diagonal entries 10753 10754 Level: developer 10755 10756 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10757 @*/ 10758 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10759 { 10760 PetscFunctionBegin; 10761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10762 PetscValidType(mat, 1); 10763 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10764 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10765 10766 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10767 PetscFunctionReturn(PETSC_SUCCESS); 10768 } 10769 10770 /*@C 10771 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10772 10773 Collective; No Fortran Support 10774 10775 Input Parameter: 10776 . mat - the matrix 10777 10778 Output Parameter: 10779 . values - the block inverses in column major order (FORTRAN-like) 10780 10781 Level: advanced 10782 10783 Notes: 10784 The size of the blocks is determined by the block size of the matrix. 10785 10786 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10787 10788 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10789 10790 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10791 @*/ 10792 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10793 { 10794 PetscFunctionBegin; 10795 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10796 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10797 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10798 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10799 PetscFunctionReturn(PETSC_SUCCESS); 10800 } 10801 10802 /*@ 10803 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10804 10805 Collective; No Fortran Support 10806 10807 Input Parameters: 10808 + mat - the matrix 10809 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10810 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10811 10812 Output Parameter: 10813 . values - the block inverses in column major order (FORTRAN-like) 10814 10815 Level: advanced 10816 10817 Notes: 10818 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10819 10820 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10821 10822 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10823 @*/ 10824 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10825 { 10826 PetscFunctionBegin; 10827 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10828 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10829 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10830 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10831 PetscFunctionReturn(PETSC_SUCCESS); 10832 } 10833 10834 /*@ 10835 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10836 10837 Collective 10838 10839 Input Parameters: 10840 + A - the matrix 10841 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10842 10843 Level: advanced 10844 10845 Note: 10846 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10847 10848 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10849 @*/ 10850 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10851 { 10852 const PetscScalar *vals; 10853 PetscInt *dnnz; 10854 PetscInt m, rstart, rend, bs, i, j; 10855 10856 PetscFunctionBegin; 10857 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10858 PetscCall(MatGetBlockSize(A, &bs)); 10859 PetscCall(MatGetLocalSize(A, &m, NULL)); 10860 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10861 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10862 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10863 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10864 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10865 PetscCall(PetscFree(dnnz)); 10866 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10867 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10868 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10869 PetscCall(MatSetOption(C, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 10870 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10871 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10872 PetscCall(MatSetOption(C, MAT_NO_OFF_PROC_ENTRIES, PETSC_FALSE)); 10873 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10874 PetscFunctionReturn(PETSC_SUCCESS); 10875 } 10876 10877 /*@ 10878 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10879 via `MatTransposeColoringCreate()`. 10880 10881 Collective 10882 10883 Input Parameter: 10884 . c - coloring context 10885 10886 Level: intermediate 10887 10888 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10889 @*/ 10890 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10891 { 10892 MatTransposeColoring matcolor = *c; 10893 10894 PetscFunctionBegin; 10895 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10896 if (--((PetscObject)matcolor)->refct > 0) { 10897 matcolor = NULL; 10898 PetscFunctionReturn(PETSC_SUCCESS); 10899 } 10900 10901 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10902 PetscCall(PetscFree(matcolor->rows)); 10903 PetscCall(PetscFree(matcolor->den2sp)); 10904 PetscCall(PetscFree(matcolor->colorforcol)); 10905 PetscCall(PetscFree(matcolor->columns)); 10906 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10907 PetscCall(PetscHeaderDestroy(c)); 10908 PetscFunctionReturn(PETSC_SUCCESS); 10909 } 10910 10911 /*@ 10912 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10913 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10914 `MatTransposeColoring` to sparse `B`. 10915 10916 Collective 10917 10918 Input Parameters: 10919 + coloring - coloring context created with `MatTransposeColoringCreate()` 10920 - B - sparse matrix 10921 10922 Output Parameter: 10923 . Btdense - dense matrix $B^T$ 10924 10925 Level: developer 10926 10927 Note: 10928 These are used internally for some implementations of `MatRARt()` 10929 10930 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10931 @*/ 10932 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10933 { 10934 PetscFunctionBegin; 10935 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10936 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10937 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10938 10939 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10940 PetscFunctionReturn(PETSC_SUCCESS); 10941 } 10942 10943 /*@ 10944 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10945 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10946 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10947 $C_{sp}$ from $C_{den}$. 10948 10949 Collective 10950 10951 Input Parameters: 10952 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10953 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10954 10955 Output Parameter: 10956 . Csp - sparse matrix 10957 10958 Level: developer 10959 10960 Note: 10961 These are used internally for some implementations of `MatRARt()` 10962 10963 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10964 @*/ 10965 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10966 { 10967 PetscFunctionBegin; 10968 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10969 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10970 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10971 10972 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10973 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10974 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10975 PetscFunctionReturn(PETSC_SUCCESS); 10976 } 10977 10978 /*@ 10979 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10980 10981 Collective 10982 10983 Input Parameters: 10984 + mat - the matrix product C 10985 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10986 10987 Output Parameter: 10988 . color - the new coloring context 10989 10990 Level: intermediate 10991 10992 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10993 `MatTransColoringApplyDenToSp()` 10994 @*/ 10995 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10996 { 10997 MatTransposeColoring c; 10998 MPI_Comm comm; 10999 11000 PetscFunctionBegin; 11001 PetscAssertPointer(color, 3); 11002 11003 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11004 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 11005 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 11006 c->ctype = iscoloring->ctype; 11007 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 11008 *color = c; 11009 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 11010 PetscFunctionReturn(PETSC_SUCCESS); 11011 } 11012 11013 /*@ 11014 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 11015 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 11016 11017 Not Collective 11018 11019 Input Parameter: 11020 . mat - the matrix 11021 11022 Output Parameter: 11023 . state - the current state 11024 11025 Level: intermediate 11026 11027 Notes: 11028 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 11029 different matrices 11030 11031 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 11032 11033 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 11034 11035 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 11036 @*/ 11037 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 11038 { 11039 PetscFunctionBegin; 11040 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11041 *state = mat->nonzerostate; 11042 PetscFunctionReturn(PETSC_SUCCESS); 11043 } 11044 11045 /*@ 11046 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11047 matrices from each processor 11048 11049 Collective 11050 11051 Input Parameters: 11052 + comm - the communicators the parallel matrix will live on 11053 . seqmat - the input sequential matrices 11054 . n - number of local columns (or `PETSC_DECIDE`) 11055 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11056 11057 Output Parameter: 11058 . mpimat - the parallel matrix generated 11059 11060 Level: developer 11061 11062 Note: 11063 The number of columns of the matrix in EACH processor MUST be the same. 11064 11065 .seealso: [](ch_matrices), `Mat` 11066 @*/ 11067 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11068 { 11069 PetscMPIInt size; 11070 11071 PetscFunctionBegin; 11072 PetscCallMPI(MPI_Comm_size(comm, &size)); 11073 if (size == 1) { 11074 if (reuse == MAT_INITIAL_MATRIX) { 11075 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11076 } else { 11077 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11078 } 11079 PetscFunctionReturn(PETSC_SUCCESS); 11080 } 11081 11082 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"); 11083 11084 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11085 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11086 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11087 PetscFunctionReturn(PETSC_SUCCESS); 11088 } 11089 11090 /*@ 11091 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11092 11093 Collective 11094 11095 Input Parameters: 11096 + A - the matrix to create subdomains from 11097 - N - requested number of subdomains 11098 11099 Output Parameters: 11100 + n - number of subdomains resulting on this MPI process 11101 - iss - `IS` list with indices of subdomains on this MPI process 11102 11103 Level: advanced 11104 11105 Note: 11106 The number of subdomains must be smaller than the communicator size 11107 11108 .seealso: [](ch_matrices), `Mat`, `IS` 11109 @*/ 11110 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11111 { 11112 MPI_Comm comm, subcomm; 11113 PetscMPIInt size, rank, color; 11114 PetscInt rstart, rend, k; 11115 11116 PetscFunctionBegin; 11117 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11118 PetscCallMPI(MPI_Comm_size(comm, &size)); 11119 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11120 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); 11121 *n = 1; 11122 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11123 color = rank / k; 11124 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11125 PetscCall(PetscMalloc1(1, iss)); 11126 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11127 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11128 PetscCallMPI(MPI_Comm_free(&subcomm)); 11129 PetscFunctionReturn(PETSC_SUCCESS); 11130 } 11131 11132 /*@ 11133 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11134 11135 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11136 If they are not the same, uses `MatMatMatMult()`. 11137 11138 Once the coarse grid problem is constructed, correct for interpolation operators 11139 that are not of full rank, which can legitimately happen in the case of non-nested 11140 geometric multigrid. 11141 11142 Input Parameters: 11143 + restrct - restriction operator 11144 . dA - fine grid matrix 11145 . interpolate - interpolation operator 11146 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11147 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11148 11149 Output Parameter: 11150 . A - the Galerkin coarse matrix 11151 11152 Options Database Key: 11153 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11154 11155 Level: developer 11156 11157 Note: 11158 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11159 11160 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11161 @*/ 11162 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11163 { 11164 IS zerorows; 11165 Vec diag; 11166 11167 PetscFunctionBegin; 11168 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11169 /* Construct the coarse grid matrix */ 11170 if (interpolate == restrct) { 11171 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11172 } else { 11173 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11174 } 11175 11176 /* If the interpolation matrix is not of full rank, A will have zero rows. 11177 This can legitimately happen in the case of non-nested geometric multigrid. 11178 In that event, we set the rows of the matrix to the rows of the identity, 11179 ignoring the equations (as the RHS will also be zero). */ 11180 11181 PetscCall(MatFindZeroRows(*A, &zerorows)); 11182 11183 if (zerorows != NULL) { /* if there are any zero rows */ 11184 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11185 PetscCall(MatGetDiagonal(*A, diag)); 11186 PetscCall(VecISSet(diag, zerorows, 1.0)); 11187 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11188 PetscCall(VecDestroy(&diag)); 11189 PetscCall(ISDestroy(&zerorows)); 11190 } 11191 PetscFunctionReturn(PETSC_SUCCESS); 11192 } 11193 11194 /*@C 11195 MatSetOperation - Allows user to set a matrix operation for any matrix type 11196 11197 Logically Collective 11198 11199 Input Parameters: 11200 + mat - the matrix 11201 . op - the name of the operation 11202 - f - the function that provides the operation 11203 11204 Level: developer 11205 11206 Example Usage: 11207 .vb 11208 extern PetscErrorCode usermult(Mat, Vec, Vec); 11209 11210 PetscCall(MatCreateXXX(comm, ..., &A)); 11211 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscErrorCodeFn *)usermult)); 11212 .ve 11213 11214 Notes: 11215 See the file `include/petscmat.h` for a complete list of matrix 11216 operations, which all have the form MATOP_<OPERATION>, where 11217 <OPERATION> is the name (in all capital letters) of the 11218 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11219 11220 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11221 sequence as the usual matrix interface routines, since they 11222 are intended to be accessed via the usual matrix interface 11223 routines, e.g., 11224 .vb 11225 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11226 .ve 11227 11228 In particular each function MUST return `PETSC_SUCCESS` on success and 11229 nonzero on failure. 11230 11231 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11232 11233 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11234 @*/ 11235 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, PetscErrorCodeFn *f) 11236 { 11237 PetscFunctionBegin; 11238 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11239 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (PetscErrorCodeFn *)mat->ops->view) mat->ops->viewnative = mat->ops->view; 11240 (((PetscErrorCodeFn **)mat->ops)[op]) = f; 11241 PetscFunctionReturn(PETSC_SUCCESS); 11242 } 11243 11244 /*@C 11245 MatGetOperation - Gets a matrix operation for any matrix type. 11246 11247 Not Collective 11248 11249 Input Parameters: 11250 + mat - the matrix 11251 - op - the name of the operation 11252 11253 Output Parameter: 11254 . f - the function that provides the operation 11255 11256 Level: developer 11257 11258 Example Usage: 11259 .vb 11260 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11261 11262 MatGetOperation(A, MATOP_MULT, (PetscErrorCodeFn **)&usermult); 11263 .ve 11264 11265 Notes: 11266 See the file `include/petscmat.h` for a complete list of matrix 11267 operations, which all have the form MATOP_<OPERATION>, where 11268 <OPERATION> is the name (in all capital letters) of the 11269 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11270 11271 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11272 11273 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11274 @*/ 11275 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, PetscErrorCodeFn **f) 11276 { 11277 PetscFunctionBegin; 11278 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11279 *f = (((PetscErrorCodeFn **)mat->ops)[op]); 11280 PetscFunctionReturn(PETSC_SUCCESS); 11281 } 11282 11283 /*@ 11284 MatHasOperation - Determines whether the given matrix supports the particular operation. 11285 11286 Not Collective 11287 11288 Input Parameters: 11289 + mat - the matrix 11290 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11291 11292 Output Parameter: 11293 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11294 11295 Level: advanced 11296 11297 Note: 11298 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11299 11300 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11301 @*/ 11302 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11303 { 11304 PetscFunctionBegin; 11305 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11306 PetscAssertPointer(has, 3); 11307 if (mat->ops->hasoperation) { 11308 PetscUseTypeMethod(mat, hasoperation, op, has); 11309 } else { 11310 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11311 else { 11312 *has = PETSC_FALSE; 11313 if (op == MATOP_CREATE_SUBMATRIX) { 11314 PetscMPIInt size; 11315 11316 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11317 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11318 } 11319 } 11320 } 11321 PetscFunctionReturn(PETSC_SUCCESS); 11322 } 11323 11324 /*@ 11325 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11326 11327 Collective 11328 11329 Input Parameter: 11330 . mat - the matrix 11331 11332 Output Parameter: 11333 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11334 11335 Level: beginner 11336 11337 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11338 @*/ 11339 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11340 { 11341 PetscFunctionBegin; 11342 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11343 PetscValidType(mat, 1); 11344 PetscAssertPointer(cong, 2); 11345 if (!mat->rmap || !mat->cmap) { 11346 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11347 PetscFunctionReturn(PETSC_SUCCESS); 11348 } 11349 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11350 PetscCall(PetscLayoutSetUp(mat->rmap)); 11351 PetscCall(PetscLayoutSetUp(mat->cmap)); 11352 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11353 if (*cong) mat->congruentlayouts = 1; 11354 else mat->congruentlayouts = 0; 11355 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11356 PetscFunctionReturn(PETSC_SUCCESS); 11357 } 11358 11359 PetscErrorCode MatSetInf(Mat A) 11360 { 11361 PetscFunctionBegin; 11362 PetscUseTypeMethod(A, setinf); 11363 PetscFunctionReturn(PETSC_SUCCESS); 11364 } 11365 11366 /*@ 11367 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 11368 and possibly removes small values from the graph structure. 11369 11370 Collective 11371 11372 Input Parameters: 11373 + A - the matrix 11374 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11375 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11376 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11377 . num_idx - size of 'index' array 11378 - index - array of block indices to use for graph strength of connection weight 11379 11380 Output Parameter: 11381 . graph - the resulting graph 11382 11383 Level: advanced 11384 11385 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11386 @*/ 11387 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11388 { 11389 PetscFunctionBegin; 11390 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11391 PetscValidType(A, 1); 11392 PetscValidLogicalCollectiveBool(A, scale, 3); 11393 PetscAssertPointer(graph, 7); 11394 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11395 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11396 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11397 PetscFunctionReturn(PETSC_SUCCESS); 11398 } 11399 11400 /*@ 11401 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11402 meaning the same memory is used for the matrix, and no new memory is allocated. 11403 11404 Collective 11405 11406 Input Parameters: 11407 + A - the matrix 11408 - 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 11409 11410 Level: intermediate 11411 11412 Developer Note: 11413 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11414 of the arrays in the data structure are unneeded. 11415 11416 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11417 @*/ 11418 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11419 { 11420 PetscFunctionBegin; 11421 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11422 PetscUseTypeMethod(A, eliminatezeros, keep); 11423 PetscFunctionReturn(PETSC_SUCCESS); 11424 } 11425 11426 /*@C 11427 MatGetCurrentMemType - Get the memory location of the matrix 11428 11429 Not Collective, but the result will be the same on all MPI processes 11430 11431 Input Parameter: 11432 . A - the matrix whose memory type we are checking 11433 11434 Output Parameter: 11435 . m - the memory type 11436 11437 Level: intermediate 11438 11439 .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`, `PetscMemType` 11440 @*/ 11441 PetscErrorCode MatGetCurrentMemType(Mat A, PetscMemType *m) 11442 { 11443 PetscFunctionBegin; 11444 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11445 PetscAssertPointer(m, 2); 11446 if (A->ops->getcurrentmemtype) PetscUseTypeMethod(A, getcurrentmemtype, m); 11447 else *m = PETSC_MEMTYPE_HOST; 11448 PetscFunctionReturn(PETSC_SUCCESS); 11449 } 11450