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; 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 4383 if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) { 4384 PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame)); 4385 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4386 } else { 4387 PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL; 4388 const char *prefix[3] = {"seq", "mpi", ""}; 4389 PetscInt i; 4390 /* 4391 Order of precedence: 4392 0) See if newtype is a superclass of the current matrix. 4393 1) See if a specialized converter is known to the current matrix. 4394 2) See if a specialized converter is known to the desired matrix class. 4395 3) See if a good general converter is registered for the desired class 4396 (as of 6/27/03 only MATMPIADJ falls into this category). 4397 4) See if a good general converter is known for the current matrix. 4398 5) Use a really basic converter. 4399 */ 4400 4401 /* 0) See if newtype is a superclass of the current matrix. 4402 i.e mat is mpiaij and newtype is aij */ 4403 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4404 PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname))); 4405 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4406 PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg)); 4407 PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg)); 4408 if (flg) { 4409 if (reuse == MAT_INPLACE_MATRIX) { 4410 PetscCall(PetscInfo(mat, "Early return\n")); 4411 PetscFunctionReturn(PETSC_SUCCESS); 4412 } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) { 4413 PetscCall(PetscInfo(mat, "Calling MatDuplicate\n")); 4414 PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M); 4415 PetscFunctionReturn(PETSC_SUCCESS); 4416 } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) { 4417 PetscCall(PetscInfo(mat, "Calling MatCopy\n")); 4418 PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN)); 4419 PetscFunctionReturn(PETSC_SUCCESS); 4420 } 4421 } 4422 } 4423 /* 1) See if a specialized converter is known to the current matrix and the desired class */ 4424 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4425 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4426 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4427 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4428 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4429 PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname))); 4430 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4431 PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv)); 4432 PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv)); 4433 if (conv) goto foundconv; 4434 } 4435 4436 /* 2) See if a specialized converter is known to the desired matrix class. */ 4437 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B)); 4438 PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 4439 PetscCall(MatSetType(B, newtype)); 4440 for (i = 0; i < (PetscInt)PETSC_STATIC_ARRAY_LENGTH(prefix); i++) { 4441 PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname))); 4442 PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname))); 4443 PetscCall(PetscStrlcat(convname, "_", sizeof(convname))); 4444 PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname))); 4445 PetscCall(PetscStrlcat(convname, newtype, sizeof(convname))); 4446 PetscCall(PetscStrlcat(convname, "_C", sizeof(convname))); 4447 PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv)); 4448 PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv)); 4449 if (conv) { 4450 PetscCall(MatDestroy(&B)); 4451 goto foundconv; 4452 } 4453 } 4454 4455 /* 3) See if a good general converter is registered for the desired class */ 4456 conv = B->ops->convertfrom; 4457 PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv)); 4458 PetscCall(MatDestroy(&B)); 4459 if (conv) goto foundconv; 4460 4461 /* 4) See if a good general converter is known for the current matrix */ 4462 if (mat->ops->convert) conv = mat->ops->convert; 4463 PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv)); 4464 if (conv) goto foundconv; 4465 4466 /* 5) Use a really basic converter. */ 4467 PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n")); 4468 conv = MatConvert_Basic; 4469 4470 foundconv: 4471 PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0)); 4472 PetscCall((*conv)(mat, newtype, reuse, M)); 4473 if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) { 4474 /* the block sizes must be same if the mappings are copied over */ 4475 (*M)->rmap->bs = mat->rmap->bs; 4476 (*M)->cmap->bs = mat->cmap->bs; 4477 PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping)); 4478 PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping)); 4479 (*M)->rmap->mapping = mat->rmap->mapping; 4480 (*M)->cmap->mapping = mat->cmap->mapping; 4481 } 4482 (*M)->stencil.dim = mat->stencil.dim; 4483 (*M)->stencil.noc = mat->stencil.noc; 4484 for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) { 4485 (*M)->stencil.dims[i] = mat->stencil.dims[i]; 4486 (*M)->stencil.starts[i] = mat->stencil.starts[i]; 4487 } 4488 PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0)); 4489 } 4490 PetscCall(PetscObjectStateIncrease((PetscObject)*M)); 4491 4492 /* Copy Mat options */ 4493 if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE)); 4494 else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE)); 4495 if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE)); 4496 else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE)); 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 } 5538 PetscFunctionReturn(PETSC_SUCCESS); 5539 } 5540 5541 /*@ 5542 MatPermute - Creates a new matrix with rows and columns permuted from the 5543 original. 5544 5545 Collective 5546 5547 Input Parameters: 5548 + mat - the matrix to permute 5549 . row - row permutation, each processor supplies only the permutation for its rows 5550 - col - column permutation, each processor supplies only the permutation for its columns 5551 5552 Output Parameter: 5553 . B - the permuted matrix 5554 5555 Level: advanced 5556 5557 Note: 5558 The index sets map from row/col of permuted matrix to row/col of original matrix. 5559 The index sets should be on the same communicator as mat and have the same local sizes. 5560 5561 Developer Note: 5562 If you want to implement `MatPermute()` for a matrix type, and your approach doesn't 5563 exploit the fact that row and col are permutations, consider implementing the 5564 more general `MatCreateSubMatrix()` instead. 5565 5566 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()` 5567 @*/ 5568 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) 5569 { 5570 PetscFunctionBegin; 5571 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5572 PetscValidType(mat, 1); 5573 PetscValidHeaderSpecific(row, IS_CLASSID, 2); 5574 PetscValidHeaderSpecific(col, IS_CLASSID, 3); 5575 PetscAssertPointer(B, 4); 5576 PetscCheckSameComm(mat, 1, row, 2); 5577 if (row != col) PetscCheckSameComm(row, 2, col, 3); 5578 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5579 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5580 PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name); 5581 MatCheckPreallocated(mat, 1); 5582 5583 if (mat->ops->permute) { 5584 PetscUseTypeMethod(mat, permute, row, col, B); 5585 PetscCall(PetscObjectStateIncrease((PetscObject)*B)); 5586 } else { 5587 PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B)); 5588 } 5589 PetscFunctionReturn(PETSC_SUCCESS); 5590 } 5591 5592 /*@ 5593 MatEqual - Compares two matrices. 5594 5595 Collective 5596 5597 Input Parameters: 5598 + A - the first matrix 5599 - B - the second matrix 5600 5601 Output Parameter: 5602 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise. 5603 5604 Level: intermediate 5605 5606 Note: 5607 If either of the matrix is "matrix-free", meaning the matrix entries are not stored explicitly then equality is determined by comparing 5608 the results of several matrix-vector product using randomly created vectors, see `MatMultEqual()`. 5609 5610 .seealso: [](ch_matrices), `Mat`, `MatMultEqual()` 5611 @*/ 5612 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) 5613 { 5614 PetscFunctionBegin; 5615 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5616 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 5617 PetscValidType(A, 1); 5618 PetscValidType(B, 2); 5619 PetscAssertPointer(flg, 3); 5620 PetscCheckSameComm(A, 1, B, 2); 5621 MatCheckPreallocated(A, 1); 5622 MatCheckPreallocated(B, 2); 5623 PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5624 PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5625 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, 5626 B->cmap->N); 5627 if (A->ops->equal && A->ops->equal == B->ops->equal) { 5628 PetscUseTypeMethod(A, equal, B, flg); 5629 } else { 5630 PetscCall(MatMultEqual(A, B, 10, flg)); 5631 } 5632 PetscFunctionReturn(PETSC_SUCCESS); 5633 } 5634 5635 /*@ 5636 MatDiagonalScale - Scales a matrix on the left and right by diagonal 5637 matrices that are stored as vectors. Either of the two scaling 5638 matrices can be `NULL`. 5639 5640 Collective 5641 5642 Input Parameters: 5643 + mat - the matrix to be scaled 5644 . l - the left scaling vector (or `NULL`) 5645 - r - the right scaling vector (or `NULL`) 5646 5647 Level: intermediate 5648 5649 Note: 5650 `MatDiagonalScale()` computes $A = LAR$, where 5651 L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector) 5652 The L scales the rows of the matrix, the R scales the columns of the matrix. 5653 5654 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()` 5655 @*/ 5656 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) 5657 { 5658 PetscFunctionBegin; 5659 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5660 PetscValidType(mat, 1); 5661 if (l) { 5662 PetscValidHeaderSpecific(l, VEC_CLASSID, 2); 5663 PetscCheckSameComm(mat, 1, l, 2); 5664 } 5665 if (r) { 5666 PetscValidHeaderSpecific(r, VEC_CLASSID, 3); 5667 PetscCheckSameComm(mat, 1, r, 3); 5668 } 5669 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5670 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5671 MatCheckPreallocated(mat, 1); 5672 if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS); 5673 5674 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5675 PetscUseTypeMethod(mat, diagonalscale, l, r); 5676 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5677 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5678 if (l != r) mat->symmetric = PETSC_BOOL3_FALSE; 5679 PetscFunctionReturn(PETSC_SUCCESS); 5680 } 5681 5682 /*@ 5683 MatScale - Scales all elements of a matrix by a given number. 5684 5685 Logically Collective 5686 5687 Input Parameters: 5688 + mat - the matrix to be scaled 5689 - a - the scaling value 5690 5691 Level: intermediate 5692 5693 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 5694 @*/ 5695 PetscErrorCode MatScale(Mat mat, PetscScalar a) 5696 { 5697 PetscFunctionBegin; 5698 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5699 PetscValidType(mat, 1); 5700 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5701 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5702 PetscValidLogicalCollectiveScalar(mat, a, 2); 5703 MatCheckPreallocated(mat, 1); 5704 5705 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 5706 if (a != (PetscScalar)1.0) { 5707 PetscUseTypeMethod(mat, scale, a); 5708 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5709 } 5710 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 5711 PetscFunctionReturn(PETSC_SUCCESS); 5712 } 5713 5714 /*@ 5715 MatNorm - Calculates various norms of a matrix. 5716 5717 Collective 5718 5719 Input Parameters: 5720 + mat - the matrix 5721 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY` 5722 5723 Output Parameter: 5724 . nrm - the resulting norm 5725 5726 Level: intermediate 5727 5728 .seealso: [](ch_matrices), `Mat` 5729 @*/ 5730 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) 5731 { 5732 PetscFunctionBegin; 5733 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5734 PetscValidType(mat, 1); 5735 PetscAssertPointer(nrm, 3); 5736 5737 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 5738 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 5739 MatCheckPreallocated(mat, 1); 5740 5741 PetscUseTypeMethod(mat, norm, type, nrm); 5742 PetscFunctionReturn(PETSC_SUCCESS); 5743 } 5744 5745 /* 5746 This variable is used to prevent counting of MatAssemblyBegin() that 5747 are called from within a MatAssemblyEnd(). 5748 */ 5749 static PetscInt MatAssemblyEnd_InUse = 0; 5750 /*@ 5751 MatAssemblyBegin - Begins assembling the matrix. This routine should 5752 be called after completing all calls to `MatSetValues()`. 5753 5754 Collective 5755 5756 Input Parameters: 5757 + mat - the matrix 5758 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5759 5760 Level: beginner 5761 5762 Notes: 5763 `MatSetValues()` generally caches the values that belong to other MPI processes. The matrix is ready to 5764 use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called. 5765 5766 Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES` 5767 in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before 5768 using the matrix. 5769 5770 ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the 5771 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 5772 a global collective operation requiring all processes that share the matrix. 5773 5774 Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed 5775 out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros 5776 before `MAT_FINAL_ASSEMBLY` so the space is not compressed out. 5777 5778 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()` 5779 @*/ 5780 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type) 5781 { 5782 PetscFunctionBegin; 5783 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5784 PetscValidType(mat, 1); 5785 MatCheckPreallocated(mat, 1); 5786 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?"); 5787 if (mat->assembled) { 5788 mat->was_assembled = PETSC_TRUE; 5789 mat->assembled = PETSC_FALSE; 5790 } 5791 5792 if (!MatAssemblyEnd_InUse) { 5793 PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0)); 5794 PetscTryTypeMethod(mat, assemblybegin, type); 5795 PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0)); 5796 } else PetscTryTypeMethod(mat, assemblybegin, type); 5797 PetscFunctionReturn(PETSC_SUCCESS); 5798 } 5799 5800 /*@ 5801 MatAssembled - Indicates if a matrix has been assembled and is ready for 5802 use; for example, in matrix-vector product. 5803 5804 Not Collective 5805 5806 Input Parameter: 5807 . mat - the matrix 5808 5809 Output Parameter: 5810 . assembled - `PETSC_TRUE` or `PETSC_FALSE` 5811 5812 Level: advanced 5813 5814 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()` 5815 @*/ 5816 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) 5817 { 5818 PetscFunctionBegin; 5819 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5820 PetscAssertPointer(assembled, 2); 5821 *assembled = mat->assembled; 5822 PetscFunctionReturn(PETSC_SUCCESS); 5823 } 5824 5825 /*@ 5826 MatAssemblyEnd - Completes assembling the matrix. This routine should 5827 be called after `MatAssemblyBegin()`. 5828 5829 Collective 5830 5831 Input Parameters: 5832 + mat - the matrix 5833 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY` 5834 5835 Options Database Keys: 5836 + -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()` 5837 . -mat_view ::ascii_info_detail - Prints more detailed info 5838 . -mat_view - Prints matrix in ASCII format 5839 . -mat_view ::ascii_matlab - Prints matrix in MATLAB format 5840 . -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`. 5841 . -display <name> - Sets display name (default is host) 5842 . -draw_pause <sec> - Sets number of seconds to pause after display 5843 . -mat_view socket - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab)) 5844 . -viewer_socket_machine <machine> - Machine to use for socket 5845 . -viewer_socket_port <port> - Port number to use for socket 5846 - -mat_view binary:filename[:append] - Save matrix to file in binary format 5847 5848 Level: beginner 5849 5850 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()` 5851 @*/ 5852 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) 5853 { 5854 static PetscInt inassm = 0; 5855 PetscBool flg = PETSC_FALSE; 5856 5857 PetscFunctionBegin; 5858 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 5859 PetscValidType(mat, 1); 5860 5861 inassm++; 5862 MatAssemblyEnd_InUse++; 5863 if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */ 5864 PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0)); 5865 PetscTryTypeMethod(mat, assemblyend, type); 5866 PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0)); 5867 } else PetscTryTypeMethod(mat, assemblyend, type); 5868 5869 /* Flush assembly is not a true assembly */ 5870 if (type != MAT_FLUSH_ASSEMBLY) { 5871 if (mat->num_ass) { 5872 if (!mat->symmetry_eternal) { 5873 mat->symmetric = PETSC_BOOL3_UNKNOWN; 5874 mat->hermitian = PETSC_BOOL3_UNKNOWN; 5875 } 5876 if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; 5877 if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN; 5878 } 5879 mat->num_ass++; 5880 mat->assembled = PETSC_TRUE; 5881 mat->ass_nonzerostate = mat->nonzerostate; 5882 } 5883 5884 mat->insertmode = NOT_SET_VALUES; 5885 MatAssemblyEnd_InUse--; 5886 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 5887 if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) { 5888 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 5889 5890 if (mat->checksymmetryonassembly) { 5891 PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg)); 5892 if (flg) { 5893 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5894 } else { 5895 PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol)); 5896 } 5897 } 5898 if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL)); 5899 } 5900 inassm--; 5901 PetscFunctionReturn(PETSC_SUCCESS); 5902 } 5903 5904 // PetscClangLinter pragma disable: -fdoc-section-header-unknown 5905 /*@ 5906 MatSetOption - Sets a parameter option for a matrix. Some options 5907 may be specific to certain storage formats. Some options 5908 determine how values will be inserted (or added). Sorted, 5909 row-oriented input will generally assemble the fastest. The default 5910 is row-oriented. 5911 5912 Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption` 5913 5914 Input Parameters: 5915 + mat - the matrix 5916 . op - the option, one of those listed below (and possibly others), 5917 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 5918 5919 Options Describing Matrix Structure: 5920 + `MAT_SPD` - symmetric positive definite 5921 . `MAT_SYMMETRIC` - symmetric in terms of both structure and value 5922 . `MAT_HERMITIAN` - transpose is the complex conjugation 5923 . `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure 5924 . `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix 5925 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix 5926 . `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix 5927 5928 These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they 5929 do not need to be computed (usually at a high cost) 5930 5931 Options For Use with `MatSetValues()`: 5932 Insert a logically dense subblock, which can be 5933 . `MAT_ROW_ORIENTED` - row-oriented (default) 5934 5935 These options reflect the data you pass in with `MatSetValues()`; it has 5936 nothing to do with how the data is stored internally in the matrix 5937 data structure. 5938 5939 When (re)assembling a matrix, we can restrict the input for 5940 efficiency/debugging purposes. These options include 5941 . `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow) 5942 . `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated 5943 . `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries 5944 . `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry 5945 . `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly 5946 . `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if 5947 any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves 5948 performance for very large process counts. 5949 - `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset 5950 of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly 5951 functions, instead sending only neighbor messages. 5952 5953 Level: intermediate 5954 5955 Notes: 5956 Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg! 5957 5958 Some options are relevant only for particular matrix types and 5959 are thus ignored by others. Other options are not supported by 5960 certain matrix types and will generate an error message if set. 5961 5962 If using Fortran to compute a matrix, one may need to 5963 use the column-oriented option (or convert to the row-oriented 5964 format). 5965 5966 `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion 5967 that would generate a new entry in the nonzero structure is instead 5968 ignored. Thus, if memory has not already been allocated for this particular 5969 data, then the insertion is ignored. For dense matrices, in which 5970 the entire array is allocated, no entries are ever ignored. 5971 Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5972 5973 `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion 5974 that would generate a new entry in the nonzero structure instead produces 5975 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 5976 5977 `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion 5978 that would generate a new entry that has not been preallocated will 5979 instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats 5980 only.) This is a useful flag when debugging matrix memory preallocation. 5981 If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction 5982 5983 `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for 5984 other processors should be dropped, rather than stashed. 5985 This is useful if you know that the "owning" processor is also 5986 always generating the correct matrix entries, so that PETSc need 5987 not transfer duplicate entries generated on another processor. 5988 5989 `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the 5990 searches during matrix assembly. When this flag is set, the hash table 5991 is created during the first matrix assembly. This hash table is 5992 used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()` 5993 to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag 5994 should be used with `MAT_USE_HASH_TABLE` flag. This option is currently 5995 supported by `MATMPIBAIJ` format only. 5996 5997 `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries 5998 are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()` 5999 6000 `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating 6001 a zero location in the matrix 6002 6003 `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types 6004 6005 `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the 6006 zero row routines and thus improves performance for very large process counts. 6007 6008 `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular 6009 part of the matrix (since they should match the upper triangular part). 6010 6011 `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a 6012 single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common 6013 with finite difference schemes with non-periodic boundary conditions. 6014 6015 Developer Note: 6016 `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other 6017 places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back 6018 to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had 6019 not changed. 6020 6021 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()` 6022 @*/ 6023 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) 6024 { 6025 PetscFunctionBegin; 6026 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6027 if (op > 0) { 6028 PetscValidLogicalCollectiveEnum(mat, op, 2); 6029 PetscValidLogicalCollectiveBool(mat, flg, 3); 6030 } 6031 6032 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); 6033 6034 switch (op) { 6035 case MAT_FORCE_DIAGONAL_ENTRIES: 6036 mat->force_diagonals = flg; 6037 PetscFunctionReturn(PETSC_SUCCESS); 6038 case MAT_NO_OFF_PROC_ENTRIES: 6039 mat->nooffprocentries = flg; 6040 PetscFunctionReturn(PETSC_SUCCESS); 6041 case MAT_SUBSET_OFF_PROC_ENTRIES: 6042 mat->assembly_subset = flg; 6043 if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */ 6044 #if !defined(PETSC_HAVE_MPIUNI) 6045 PetscCall(MatStashScatterDestroy_BTS(&mat->stash)); 6046 #endif 6047 mat->stash.first_assembly_done = PETSC_FALSE; 6048 } 6049 PetscFunctionReturn(PETSC_SUCCESS); 6050 case MAT_NO_OFF_PROC_ZERO_ROWS: 6051 mat->nooffproczerorows = flg; 6052 PetscFunctionReturn(PETSC_SUCCESS); 6053 case MAT_SPD: 6054 if (flg) { 6055 mat->spd = PETSC_BOOL3_TRUE; 6056 mat->symmetric = PETSC_BOOL3_TRUE; 6057 mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6058 } else { 6059 mat->spd = PETSC_BOOL3_FALSE; 6060 } 6061 break; 6062 case MAT_SYMMETRIC: 6063 mat->symmetric = PetscBoolToBool3(flg); 6064 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6065 #if !defined(PETSC_USE_COMPLEX) 6066 mat->hermitian = PetscBoolToBool3(flg); 6067 #endif 6068 break; 6069 case MAT_HERMITIAN: 6070 mat->hermitian = PetscBoolToBool3(flg); 6071 if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE; 6072 #if !defined(PETSC_USE_COMPLEX) 6073 mat->symmetric = PetscBoolToBool3(flg); 6074 #endif 6075 break; 6076 case MAT_STRUCTURALLY_SYMMETRIC: 6077 mat->structurally_symmetric = PetscBoolToBool3(flg); 6078 break; 6079 case MAT_SYMMETRY_ETERNAL: 6080 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"); 6081 mat->symmetry_eternal = flg; 6082 if (flg) mat->structural_symmetry_eternal = PETSC_TRUE; 6083 break; 6084 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6085 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"); 6086 mat->structural_symmetry_eternal = flg; 6087 break; 6088 case MAT_SPD_ETERNAL: 6089 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"); 6090 mat->spd_eternal = flg; 6091 if (flg) { 6092 mat->structural_symmetry_eternal = PETSC_TRUE; 6093 mat->symmetry_eternal = PETSC_TRUE; 6094 } 6095 break; 6096 case MAT_STRUCTURE_ONLY: 6097 mat->structure_only = flg; 6098 break; 6099 case MAT_SORTED_FULL: 6100 mat->sortedfull = flg; 6101 break; 6102 default: 6103 break; 6104 } 6105 PetscTryTypeMethod(mat, setoption, op, flg); 6106 PetscFunctionReturn(PETSC_SUCCESS); 6107 } 6108 6109 /*@ 6110 MatGetOption - Gets a parameter option that has been set for a matrix. 6111 6112 Logically Collective 6113 6114 Input Parameters: 6115 + mat - the matrix 6116 - op - the option, this only responds to certain options, check the code for which ones 6117 6118 Output Parameter: 6119 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`) 6120 6121 Level: intermediate 6122 6123 Notes: 6124 Can only be called after `MatSetSizes()` and `MatSetType()` have been set. 6125 6126 Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or 6127 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6128 6129 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, 6130 `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 6131 @*/ 6132 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) 6133 { 6134 PetscFunctionBegin; 6135 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6136 PetscValidType(mat, 1); 6137 6138 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); 6139 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()"); 6140 6141 switch (op) { 6142 case MAT_NO_OFF_PROC_ENTRIES: 6143 *flg = mat->nooffprocentries; 6144 break; 6145 case MAT_NO_OFF_PROC_ZERO_ROWS: 6146 *flg = mat->nooffproczerorows; 6147 break; 6148 case MAT_SYMMETRIC: 6149 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); 6150 break; 6151 case MAT_HERMITIAN: 6152 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); 6153 break; 6154 case MAT_STRUCTURALLY_SYMMETRIC: 6155 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); 6156 break; 6157 case MAT_SPD: 6158 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); 6159 break; 6160 case MAT_SYMMETRY_ETERNAL: 6161 *flg = mat->symmetry_eternal; 6162 break; 6163 case MAT_STRUCTURAL_SYMMETRY_ETERNAL: 6164 *flg = mat->symmetry_eternal; 6165 break; 6166 default: 6167 break; 6168 } 6169 PetscFunctionReturn(PETSC_SUCCESS); 6170 } 6171 6172 /*@ 6173 MatZeroEntries - Zeros all entries of a matrix. For sparse matrices 6174 this routine retains the old nonzero structure. 6175 6176 Logically Collective 6177 6178 Input Parameter: 6179 . mat - the matrix 6180 6181 Level: intermediate 6182 6183 Note: 6184 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. 6185 See the Performance chapter of the users manual for information on preallocating matrices. 6186 6187 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()` 6188 @*/ 6189 PetscErrorCode MatZeroEntries(Mat mat) 6190 { 6191 PetscFunctionBegin; 6192 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6193 PetscValidType(mat, 1); 6194 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6195 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"); 6196 MatCheckPreallocated(mat, 1); 6197 6198 PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0)); 6199 PetscUseTypeMethod(mat, zeroentries); 6200 PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0)); 6201 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6202 PetscFunctionReturn(PETSC_SUCCESS); 6203 } 6204 6205 /*@ 6206 MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal) 6207 of a set of rows and columns of a matrix. 6208 6209 Collective 6210 6211 Input Parameters: 6212 + mat - the matrix 6213 . numRows - the number of rows/columns to zero 6214 . rows - the global row indices 6215 . diag - value put in the diagonal of the eliminated rows 6216 . x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call 6217 - b - optional vector of the right-hand side, that will be adjusted by provided solution entries 6218 6219 Level: intermediate 6220 6221 Notes: 6222 This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6223 6224 For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`. 6225 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 6226 6227 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6228 Krylov method to take advantage of the known solution on the zeroed rows. 6229 6230 For the parallel case, all processes that share the matrix (i.e., 6231 those in the communicator used for matrix creation) MUST call this 6232 routine, regardless of whether any rows being zeroed are owned by 6233 them. 6234 6235 Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never 6236 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 6237 missing. 6238 6239 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6240 list only rows local to itself). 6241 6242 The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine. 6243 6244 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6245 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6246 @*/ 6247 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6248 { 6249 PetscFunctionBegin; 6250 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6251 PetscValidType(mat, 1); 6252 if (numRows) PetscAssertPointer(rows, 3); 6253 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6254 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6255 MatCheckPreallocated(mat, 1); 6256 6257 PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b); 6258 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6259 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6260 PetscFunctionReturn(PETSC_SUCCESS); 6261 } 6262 6263 /*@ 6264 MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal) 6265 of a set of rows and columns of a matrix. 6266 6267 Collective 6268 6269 Input Parameters: 6270 + mat - the matrix 6271 . is - the rows to zero 6272 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6273 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6274 - b - optional vector of right-hand side, that will be adjusted by provided solution 6275 6276 Level: intermediate 6277 6278 Note: 6279 See `MatZeroRowsColumns()` for details on how this routine operates. 6280 6281 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6282 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()` 6283 @*/ 6284 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6285 { 6286 PetscInt numRows; 6287 const PetscInt *rows; 6288 6289 PetscFunctionBegin; 6290 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6291 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6292 PetscValidType(mat, 1); 6293 PetscValidType(is, 2); 6294 PetscCall(ISGetLocalSize(is, &numRows)); 6295 PetscCall(ISGetIndices(is, &rows)); 6296 PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b)); 6297 PetscCall(ISRestoreIndices(is, &rows)); 6298 PetscFunctionReturn(PETSC_SUCCESS); 6299 } 6300 6301 /*@ 6302 MatZeroRows - Zeros all entries (except possibly the main diagonal) 6303 of a set of rows of a matrix. 6304 6305 Collective 6306 6307 Input Parameters: 6308 + mat - the matrix 6309 . numRows - the number of rows to zero 6310 . rows - the global row indices 6311 . diag - value put in the diagonal of the zeroed rows 6312 . x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call 6313 - b - optional vector of right-hand side, that will be adjusted by provided solution entries 6314 6315 Level: intermediate 6316 6317 Notes: 6318 This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system. 6319 6320 For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`. 6321 6322 If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the 6323 Krylov method to take advantage of the known solution on the zeroed rows. 6324 6325 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) 6326 from the matrix. 6327 6328 Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix 6329 but does not release memory. Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense 6330 formats this does not alter the nonzero structure. 6331 6332 If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure 6333 of the matrix is not changed the values are 6334 merely zeroed. 6335 6336 The user can set a value in the diagonal entry (or for the `MATAIJ` format 6337 formats can optionally remove the main diagonal entry from the 6338 nonzero structure as well, by passing 0.0 as the final argument). 6339 6340 For the parallel case, all processes that share the matrix (i.e., 6341 those in the communicator used for matrix creation) MUST call this 6342 routine, regardless of whether any rows being zeroed are owned by 6343 them. 6344 6345 Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to 6346 list only rows local to itself). 6347 6348 You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it 6349 owns that are to be zeroed. This saves a global synchronization in the implementation. 6350 6351 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6352 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN` 6353 @*/ 6354 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6355 { 6356 PetscFunctionBegin; 6357 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6358 PetscValidType(mat, 1); 6359 if (numRows) PetscAssertPointer(rows, 3); 6360 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6361 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6362 MatCheckPreallocated(mat, 1); 6363 6364 PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b); 6365 PetscCall(MatViewFromOptions(mat, NULL, "-mat_view")); 6366 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6367 PetscFunctionReturn(PETSC_SUCCESS); 6368 } 6369 6370 /*@ 6371 MatZeroRowsIS - Zeros all entries (except possibly the main diagonal) 6372 of a set of rows of a matrix indicated by an `IS` 6373 6374 Collective 6375 6376 Input Parameters: 6377 + mat - the matrix 6378 . is - index set, `IS`, of rows to remove (if `NULL` then no row is removed) 6379 . diag - value put in all diagonals of eliminated rows 6380 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6381 - b - optional vector of right-hand side, that will be adjusted by provided solution 6382 6383 Level: intermediate 6384 6385 Note: 6386 See `MatZeroRows()` for details on how this routine operates. 6387 6388 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6389 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS` 6390 @*/ 6391 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6392 { 6393 PetscInt numRows = 0; 6394 const PetscInt *rows = NULL; 6395 6396 PetscFunctionBegin; 6397 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6398 PetscValidType(mat, 1); 6399 if (is) { 6400 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6401 PetscCall(ISGetLocalSize(is, &numRows)); 6402 PetscCall(ISGetIndices(is, &rows)); 6403 } 6404 PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b)); 6405 if (is) PetscCall(ISRestoreIndices(is, &rows)); 6406 PetscFunctionReturn(PETSC_SUCCESS); 6407 } 6408 6409 /*@ 6410 MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal) 6411 of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process. 6412 6413 Collective 6414 6415 Input Parameters: 6416 + mat - the matrix 6417 . numRows - the number of rows to remove 6418 . rows - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil` 6419 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6420 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6421 - b - optional vector of right-hand side, that will be adjusted by provided solution 6422 6423 Level: intermediate 6424 6425 Notes: 6426 See `MatZeroRows()` for details on how this routine operates. 6427 6428 The grid coordinates are across the entire grid, not just the local portion 6429 6430 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6431 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6432 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6433 `DM_BOUNDARY_PERIODIC` boundary type. 6434 6435 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 6436 a single value per point) you can skip filling those indices. 6437 6438 Fortran Note: 6439 `idxm` and `idxn` should be declared as 6440 .vb 6441 MatStencil idxm(4, m) 6442 .ve 6443 and the values inserted using 6444 .vb 6445 idxm(MatStencil_i, 1) = i 6446 idxm(MatStencil_j, 1) = j 6447 idxm(MatStencil_k, 1) = k 6448 idxm(MatStencil_c, 1) = c 6449 etc 6450 .ve 6451 6452 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6453 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6454 @*/ 6455 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6456 { 6457 PetscInt dim = mat->stencil.dim; 6458 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6459 PetscInt *dims = mat->stencil.dims + 1; 6460 PetscInt *starts = mat->stencil.starts; 6461 PetscInt *dxm = (PetscInt *)rows; 6462 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6463 6464 PetscFunctionBegin; 6465 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6466 PetscValidType(mat, 1); 6467 if (numRows) PetscAssertPointer(rows, 3); 6468 6469 PetscCall(PetscMalloc1(numRows, &jdxm)); 6470 for (i = 0; i < numRows; ++i) { 6471 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6472 for (j = 0; j < 3 - sdim; ++j) dxm++; 6473 /* Local index in X dir */ 6474 tmp = *dxm++ - starts[0]; 6475 /* Loop over remaining dimensions */ 6476 for (j = 0; j < dim - 1; ++j) { 6477 /* If nonlocal, set index to be negative */ 6478 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6479 /* Update local index */ 6480 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6481 } 6482 /* Skip component slot if necessary */ 6483 if (mat->stencil.noc) dxm++; 6484 /* Local row number */ 6485 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6486 } 6487 PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b)); 6488 PetscCall(PetscFree(jdxm)); 6489 PetscFunctionReturn(PETSC_SUCCESS); 6490 } 6491 6492 /*@ 6493 MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal) 6494 of a set of rows and columns of a matrix. 6495 6496 Collective 6497 6498 Input Parameters: 6499 + mat - the matrix 6500 . numRows - the number of rows/columns to remove 6501 . rows - the grid coordinates (and component number when dof > 1) for matrix rows 6502 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry) 6503 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6504 - b - optional vector of right-hand side, that will be adjusted by provided solution 6505 6506 Level: intermediate 6507 6508 Notes: 6509 See `MatZeroRowsColumns()` for details on how this routine operates. 6510 6511 The grid coordinates are across the entire grid, not just the local portion 6512 6513 For periodic boundary conditions use negative indices for values to the left (below 0; that are to be 6514 obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one 6515 etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the 6516 `DM_BOUNDARY_PERIODIC` boundary type. 6517 6518 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 6519 a single value per point) you can skip filling those indices. 6520 6521 Fortran Note: 6522 `idxm` and `idxn` should be declared as 6523 .vb 6524 MatStencil idxm(4, m) 6525 .ve 6526 and the values inserted using 6527 .vb 6528 idxm(MatStencil_i, 1) = i 6529 idxm(MatStencil_j, 1) = j 6530 idxm(MatStencil_k, 1) = k 6531 idxm(MatStencil_c, 1) = c 6532 etc 6533 .ve 6534 6535 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6536 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()` 6537 @*/ 6538 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) 6539 { 6540 PetscInt dim = mat->stencil.dim; 6541 PetscInt sdim = dim - (1 - (PetscInt)mat->stencil.noc); 6542 PetscInt *dims = mat->stencil.dims + 1; 6543 PetscInt *starts = mat->stencil.starts; 6544 PetscInt *dxm = (PetscInt *)rows; 6545 PetscInt *jdxm, i, j, tmp, numNewRows = 0; 6546 6547 PetscFunctionBegin; 6548 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6549 PetscValidType(mat, 1); 6550 if (numRows) PetscAssertPointer(rows, 3); 6551 6552 PetscCall(PetscMalloc1(numRows, &jdxm)); 6553 for (i = 0; i < numRows; ++i) { 6554 /* Skip unused dimensions (they are ordered k, j, i, c) */ 6555 for (j = 0; j < 3 - sdim; ++j) dxm++; 6556 /* Local index in X dir */ 6557 tmp = *dxm++ - starts[0]; 6558 /* Loop over remaining dimensions */ 6559 for (j = 0; j < dim - 1; ++j) { 6560 /* If nonlocal, set index to be negative */ 6561 if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN; 6562 /* Update local index */ 6563 else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1]; 6564 } 6565 /* Skip component slot if necessary */ 6566 if (mat->stencil.noc) dxm++; 6567 /* Local row number */ 6568 if (tmp >= 0) jdxm[numNewRows++] = tmp; 6569 } 6570 PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b)); 6571 PetscCall(PetscFree(jdxm)); 6572 PetscFunctionReturn(PETSC_SUCCESS); 6573 } 6574 6575 /*@ 6576 MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal) 6577 of a set of rows of a matrix; using local numbering of rows. 6578 6579 Collective 6580 6581 Input Parameters: 6582 + mat - the matrix 6583 . numRows - the number of rows to remove 6584 . rows - the local row indices 6585 . diag - value put in all diagonals of eliminated rows 6586 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6587 - b - optional vector of right-hand side, that will be adjusted by provided solution 6588 6589 Level: intermediate 6590 6591 Notes: 6592 Before calling `MatZeroRowsLocal()`, the user must first set the 6593 local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`. 6594 6595 See `MatZeroRows()` for details on how this routine operates. 6596 6597 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`, 6598 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6599 @*/ 6600 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6601 { 6602 PetscFunctionBegin; 6603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6604 PetscValidType(mat, 1); 6605 if (numRows) PetscAssertPointer(rows, 3); 6606 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6607 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6608 MatCheckPreallocated(mat, 1); 6609 6610 if (mat->ops->zerorowslocal) { 6611 PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b); 6612 } else { 6613 IS is, newis; 6614 PetscInt *newRows, nl = 0; 6615 6616 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6617 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_USE_POINTER, &is)); 6618 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6619 PetscCall(ISGetIndices(newis, (const PetscInt **)&newRows)); 6620 for (PetscInt i = 0; i < numRows; i++) 6621 if (newRows[i] > -1) newRows[nl++] = newRows[i]; 6622 PetscUseTypeMethod(mat, zerorows, nl, newRows, diag, x, b); 6623 PetscCall(ISRestoreIndices(newis, (const PetscInt **)&newRows)); 6624 PetscCall(ISDestroy(&newis)); 6625 PetscCall(ISDestroy(&is)); 6626 } 6627 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6628 PetscFunctionReturn(PETSC_SUCCESS); 6629 } 6630 6631 /*@ 6632 MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal) 6633 of a set of rows of a matrix; using local numbering of rows. 6634 6635 Collective 6636 6637 Input Parameters: 6638 + mat - the matrix 6639 . is - index set of rows to remove 6640 . diag - value put in all diagonals of eliminated rows 6641 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6642 - b - optional vector of right-hand side, that will be adjusted by provided solution 6643 6644 Level: intermediate 6645 6646 Notes: 6647 Before calling `MatZeroRowsLocalIS()`, the user must first set the 6648 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6649 6650 See `MatZeroRows()` for details on how this routine operates. 6651 6652 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6653 `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6654 @*/ 6655 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6656 { 6657 PetscInt numRows; 6658 const PetscInt *rows; 6659 6660 PetscFunctionBegin; 6661 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6662 PetscValidType(mat, 1); 6663 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6664 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6665 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6666 MatCheckPreallocated(mat, 1); 6667 6668 PetscCall(ISGetLocalSize(is, &numRows)); 6669 PetscCall(ISGetIndices(is, &rows)); 6670 PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b)); 6671 PetscCall(ISRestoreIndices(is, &rows)); 6672 PetscFunctionReturn(PETSC_SUCCESS); 6673 } 6674 6675 /*@ 6676 MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal) 6677 of a set of rows and columns of a matrix; using local numbering of rows. 6678 6679 Collective 6680 6681 Input Parameters: 6682 + mat - the matrix 6683 . numRows - the number of rows to remove 6684 . rows - the global row indices 6685 . diag - value put in all diagonals of eliminated rows 6686 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6687 - b - optional vector of right-hand side, that will be adjusted by provided solution 6688 6689 Level: intermediate 6690 6691 Notes: 6692 Before calling `MatZeroRowsColumnsLocal()`, the user must first set the 6693 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6694 6695 See `MatZeroRowsColumns()` for details on how this routine operates. 6696 6697 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6698 `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6699 @*/ 6700 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) 6701 { 6702 PetscFunctionBegin; 6703 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6704 PetscValidType(mat, 1); 6705 if (numRows) PetscAssertPointer(rows, 3); 6706 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6707 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6708 MatCheckPreallocated(mat, 1); 6709 6710 if (mat->ops->zerorowscolumnslocal) { 6711 PetscUseTypeMethod(mat, zerorowscolumnslocal, numRows, rows, diag, x, b); 6712 } else { 6713 IS is, newis; 6714 PetscInt *newRows, nl = 0; 6715 6716 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first"); 6717 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_USE_POINTER, &is)); 6718 PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis)); 6719 PetscCall(ISGetIndices(newis, (const PetscInt **)&newRows)); 6720 for (PetscInt i = 0; i < numRows; i++) 6721 if (newRows[i] > -1) newRows[nl++] = newRows[i]; 6722 PetscUseTypeMethod(mat, zerorowscolumns, nl, newRows, diag, x, b); 6723 PetscCall(ISRestoreIndices(newis, (const PetscInt **)&newRows)); 6724 PetscCall(ISDestroy(&newis)); 6725 PetscCall(ISDestroy(&is)); 6726 } 6727 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 6728 PetscFunctionReturn(PETSC_SUCCESS); 6729 } 6730 6731 /*@ 6732 MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal) 6733 of a set of rows and columns of a matrix; using local numbering of rows. 6734 6735 Collective 6736 6737 Input Parameters: 6738 + mat - the matrix 6739 . is - index set of rows to remove 6740 . diag - value put in all diagonals of eliminated rows 6741 . x - optional vector of solutions for zeroed rows (other entries in vector are not used) 6742 - b - optional vector of right-hand side, that will be adjusted by provided solution 6743 6744 Level: intermediate 6745 6746 Notes: 6747 Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the 6748 local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`. 6749 6750 See `MatZeroRowsColumns()` for details on how this routine operates. 6751 6752 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`, 6753 `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()` 6754 @*/ 6755 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) 6756 { 6757 PetscInt numRows; 6758 const PetscInt *rows; 6759 6760 PetscFunctionBegin; 6761 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6762 PetscValidType(mat, 1); 6763 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 6764 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 6765 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 6766 MatCheckPreallocated(mat, 1); 6767 6768 PetscCall(ISGetLocalSize(is, &numRows)); 6769 PetscCall(ISGetIndices(is, &rows)); 6770 PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b)); 6771 PetscCall(ISRestoreIndices(is, &rows)); 6772 PetscFunctionReturn(PETSC_SUCCESS); 6773 } 6774 6775 /*@ 6776 MatGetSize - Returns the numbers of rows and columns in a matrix. 6777 6778 Not Collective 6779 6780 Input Parameter: 6781 . mat - the matrix 6782 6783 Output Parameters: 6784 + m - the number of global rows 6785 - n - the number of global columns 6786 6787 Level: beginner 6788 6789 Note: 6790 Both output parameters can be `NULL` on input. 6791 6792 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()` 6793 @*/ 6794 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) 6795 { 6796 PetscFunctionBegin; 6797 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6798 if (m) *m = mat->rmap->N; 6799 if (n) *n = mat->cmap->N; 6800 PetscFunctionReturn(PETSC_SUCCESS); 6801 } 6802 6803 /*@ 6804 MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns 6805 of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`. 6806 6807 Not Collective 6808 6809 Input Parameter: 6810 . mat - the matrix 6811 6812 Output Parameters: 6813 + m - the number of local rows, use `NULL` to not obtain this value 6814 - n - the number of local columns, use `NULL` to not obtain this value 6815 6816 Level: beginner 6817 6818 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()` 6819 @*/ 6820 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) 6821 { 6822 PetscFunctionBegin; 6823 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6824 if (m) PetscAssertPointer(m, 2); 6825 if (n) PetscAssertPointer(n, 3); 6826 if (m) *m = mat->rmap->n; 6827 if (n) *n = mat->cmap->n; 6828 PetscFunctionReturn(PETSC_SUCCESS); 6829 } 6830 6831 /*@ 6832 MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a 6833 vector one multiplies this matrix by that are owned by this processor. 6834 6835 Not Collective, unless matrix has not been allocated, then collective 6836 6837 Input Parameter: 6838 . mat - the matrix 6839 6840 Output Parameters: 6841 + m - the global index of the first local column, use `NULL` to not obtain this value 6842 - n - one more than the global index of the last local column, use `NULL` to not obtain this value 6843 6844 Level: developer 6845 6846 Notes: 6847 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6848 6849 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6850 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6851 6852 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6853 the local values in the matrix. 6854 6855 Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix 6856 Layouts](sec_matlayout) for details on matrix layouts. 6857 6858 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6859 `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6860 @*/ 6861 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) 6862 { 6863 PetscFunctionBegin; 6864 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6865 PetscValidType(mat, 1); 6866 if (m) PetscAssertPointer(m, 2); 6867 if (n) PetscAssertPointer(n, 3); 6868 MatCheckPreallocated(mat, 1); 6869 if (m) *m = mat->cmap->rstart; 6870 if (n) *n = mat->cmap->rend; 6871 PetscFunctionReturn(PETSC_SUCCESS); 6872 } 6873 6874 /*@ 6875 MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by 6876 this MPI process. 6877 6878 Not Collective 6879 6880 Input Parameter: 6881 . mat - the matrix 6882 6883 Output Parameters: 6884 + m - the global index of the first local row, use `NULL` to not obtain this value 6885 - n - one more than the global index of the last local row, use `NULL` to not obtain this value 6886 6887 Level: beginner 6888 6889 Notes: 6890 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6891 6892 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6893 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6894 6895 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6896 the local values in the matrix. 6897 6898 The high argument is one more than the last element stored locally. 6899 6900 For all matrices it returns the range of matrix rows associated with rows of a vector that 6901 would contain the result of a matrix vector product with this matrix. See [Matrix 6902 Layouts](sec_matlayout) for details on matrix layouts. 6903 6904 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, 6905 `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM` 6906 @*/ 6907 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) 6908 { 6909 PetscFunctionBegin; 6910 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6911 PetscValidType(mat, 1); 6912 if (m) PetscAssertPointer(m, 2); 6913 if (n) PetscAssertPointer(n, 3); 6914 MatCheckPreallocated(mat, 1); 6915 if (m) *m = mat->rmap->rstart; 6916 if (n) *n = mat->rmap->rend; 6917 PetscFunctionReturn(PETSC_SUCCESS); 6918 } 6919 6920 /*@C 6921 MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and 6922 `MATSCALAPACK`, returns the range of matrix rows owned by each process. 6923 6924 Not Collective, unless matrix has not been allocated 6925 6926 Input Parameter: 6927 . mat - the matrix 6928 6929 Output Parameter: 6930 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1 6931 where `size` is the number of MPI processes used by `mat` 6932 6933 Level: beginner 6934 6935 Notes: 6936 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6937 6938 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6939 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6940 6941 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6942 the local values in the matrix. 6943 6944 For all matrices it returns the ranges of matrix rows associated with rows of a vector that 6945 would contain the result of a matrix vector product with this matrix. See [Matrix 6946 Layouts](sec_matlayout) for details on matrix layouts. 6947 6948 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`, 6949 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`, 6950 `DMDAGetGhostCorners()`, `DM` 6951 @*/ 6952 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[]) 6953 { 6954 PetscFunctionBegin; 6955 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6956 PetscValidType(mat, 1); 6957 MatCheckPreallocated(mat, 1); 6958 PetscCall(PetscLayoutGetRanges(mat->rmap, ranges)); 6959 PetscFunctionReturn(PETSC_SUCCESS); 6960 } 6961 6962 /*@C 6963 MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a 6964 vector one multiplies this vector by that are owned by each processor. 6965 6966 Not Collective, unless matrix has not been allocated 6967 6968 Input Parameter: 6969 . mat - the matrix 6970 6971 Output Parameter: 6972 . ranges - start of each processors portion plus one more than the total length at the end 6973 6974 Level: beginner 6975 6976 Notes: 6977 If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`. 6978 6979 If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`. 6980 If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`. 6981 6982 For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine 6983 the local values in the matrix. 6984 6985 Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix 6986 Layouts](sec_matlayout) for details on matrix layouts. 6987 6988 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`, 6989 `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, 6990 `DMDAGetGhostCorners()`, `DM` 6991 @*/ 6992 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[]) 6993 { 6994 PetscFunctionBegin; 6995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 6996 PetscValidType(mat, 1); 6997 MatCheckPreallocated(mat, 1); 6998 PetscCall(PetscLayoutGetRanges(mat->cmap, ranges)); 6999 PetscFunctionReturn(PETSC_SUCCESS); 7000 } 7001 7002 /*@ 7003 MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. 7004 7005 Not Collective 7006 7007 Input Parameter: 7008 . A - matrix 7009 7010 Output Parameters: 7011 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value 7012 - cols - columns in which this process owns elements, use `NULL` to not obtain this value 7013 7014 Level: intermediate 7015 7016 Note: 7017 You should call `ISDestroy()` on the returned `IS` 7018 7019 For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values 7020 returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and 7021 `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for 7022 details on matrix layouts. 7023 7024 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK` 7025 @*/ 7026 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) 7027 { 7028 PetscErrorCode (*f)(Mat, IS *, IS *); 7029 7030 PetscFunctionBegin; 7031 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 7032 PetscValidType(A, 1); 7033 MatCheckPreallocated(A, 1); 7034 PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f)); 7035 if (f) { 7036 PetscCall((*f)(A, rows, cols)); 7037 } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */ 7038 if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows)); 7039 if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols)); 7040 } 7041 PetscFunctionReturn(PETSC_SUCCESS); 7042 } 7043 7044 /*@ 7045 MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()` 7046 Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()` 7047 to complete the factorization. 7048 7049 Collective 7050 7051 Input Parameters: 7052 + fact - the factorized matrix obtained with `MatGetFactor()` 7053 . mat - the matrix 7054 . row - row permutation 7055 . col - column permutation 7056 - info - structure containing 7057 .vb 7058 levels - number of levels of fill. 7059 expected fill - as ratio of original fill. 7060 1 or 0 - indicating force fill on diagonal (improves robustness for matrices 7061 missing diagonal entries) 7062 .ve 7063 7064 Level: developer 7065 7066 Notes: 7067 See [Matrix Factorization](sec_matfactor) for additional information. 7068 7069 Most users should employ the `KSP` interface for linear solvers 7070 instead of working directly with matrix algebra routines such as this. 7071 See, e.g., `KSPCreate()`. 7072 7073 Uses the definition of level of fill as in Y. Saad, {cite}`saad2003` 7074 7075 Fortran Note: 7076 A valid (non-null) `info` argument must be provided 7077 7078 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 7079 `MatGetOrdering()`, `MatFactorInfo` 7080 @*/ 7081 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) 7082 { 7083 PetscFunctionBegin; 7084 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7085 PetscValidType(mat, 2); 7086 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3); 7087 if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4); 7088 PetscAssertPointer(info, 5); 7089 PetscAssertPointer(fact, 1); 7090 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels); 7091 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7092 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7093 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7094 MatCheckPreallocated(mat, 2); 7095 7096 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7097 PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info); 7098 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0)); 7099 PetscFunctionReturn(PETSC_SUCCESS); 7100 } 7101 7102 /*@ 7103 MatICCFactorSymbolic - Performs symbolic incomplete 7104 Cholesky factorization for a symmetric matrix. Use 7105 `MatCholeskyFactorNumeric()` to complete the factorization. 7106 7107 Collective 7108 7109 Input Parameters: 7110 + fact - the factorized matrix obtained with `MatGetFactor()` 7111 . mat - the matrix to be factored 7112 . perm - row and column permutation 7113 - info - structure containing 7114 .vb 7115 levels - number of levels of fill. 7116 expected fill - as ratio of original fill. 7117 .ve 7118 7119 Level: developer 7120 7121 Notes: 7122 Most users should employ the `KSP` interface for linear solvers 7123 instead of working directly with matrix algebra routines such as this. 7124 See, e.g., `KSPCreate()`. 7125 7126 This uses the definition of level of fill as in Y. Saad {cite}`saad2003` 7127 7128 Fortran Note: 7129 A valid (non-null) `info` argument must be provided 7130 7131 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo` 7132 @*/ 7133 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) 7134 { 7135 PetscFunctionBegin; 7136 PetscValidHeaderSpecific(mat, MAT_CLASSID, 2); 7137 PetscValidType(mat, 2); 7138 if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3); 7139 PetscAssertPointer(info, 4); 7140 PetscAssertPointer(fact, 1); 7141 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7142 PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels); 7143 PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill); 7144 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7145 MatCheckPreallocated(mat, 2); 7146 7147 if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7148 PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info); 7149 if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0)); 7150 PetscFunctionReturn(PETSC_SUCCESS); 7151 } 7152 7153 /*@C 7154 MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat 7155 points to an array of valid matrices, they may be reused to store the new 7156 submatrices. 7157 7158 Collective 7159 7160 Input Parameters: 7161 + mat - the matrix 7162 . n - the number of submatrixes to be extracted (on this processor, may be zero) 7163 . irow - index set of rows to extract 7164 . icol - index set of columns to extract 7165 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7166 7167 Output Parameter: 7168 . submat - the array of submatrices 7169 7170 Level: advanced 7171 7172 Notes: 7173 `MatCreateSubMatrices()` can extract ONLY sequential submatrices 7174 (from both sequential and parallel matrices). Use `MatCreateSubMatrix()` 7175 to extract a parallel submatrix. 7176 7177 Some matrix types place restrictions on the row and column 7178 indices, such as that they be sorted or that they be equal to each other. 7179 7180 The index sets may not have duplicate entries. 7181 7182 When extracting submatrices from a parallel matrix, each processor can 7183 form a different submatrix by setting the rows and columns of its 7184 individual index sets according to the local submatrix desired. 7185 7186 When finished using the submatrices, the user should destroy 7187 them with `MatDestroySubMatrices()`. 7188 7189 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 7190 original matrix has not changed from that last call to `MatCreateSubMatrices()`. 7191 7192 This routine creates the matrices in submat; you should NOT create them before 7193 calling it. It also allocates the array of matrix pointers submat. 7194 7195 For `MATBAIJ` matrices the index sets must respect the block structure, that is if they 7196 request one row/column in a block, they must request all rows/columns that are in 7197 that block. For example, if the block size is 2 you cannot request just row 0 and 7198 column 0. 7199 7200 Fortran Note: 7201 .vb 7202 Mat, pointer :: submat(:) 7203 .ve 7204 7205 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7206 @*/ 7207 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7208 { 7209 PetscInt i; 7210 PetscBool eq; 7211 7212 PetscFunctionBegin; 7213 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7214 PetscValidType(mat, 1); 7215 if (n) { 7216 PetscAssertPointer(irow, 3); 7217 for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3); 7218 PetscAssertPointer(icol, 4); 7219 for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4); 7220 } 7221 PetscAssertPointer(submat, 6); 7222 if (n && scall == MAT_REUSE_MATRIX) { 7223 PetscAssertPointer(*submat, 6); 7224 for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6); 7225 } 7226 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7227 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7228 MatCheckPreallocated(mat, 1); 7229 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7230 PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat); 7231 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7232 for (i = 0; i < n; i++) { 7233 (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */ 7234 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7235 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7236 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 7237 if (mat->boundtocpu && mat->bindingpropagates) { 7238 PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE)); 7239 PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE)); 7240 } 7241 #endif 7242 } 7243 PetscFunctionReturn(PETSC_SUCCESS); 7244 } 7245 7246 /*@C 7247 MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of `mat` (by pairs of `IS` that may live on subcomms). 7248 7249 Collective 7250 7251 Input Parameters: 7252 + mat - the matrix 7253 . n - the number of submatrixes to be extracted 7254 . irow - index set of rows to extract 7255 . icol - index set of columns to extract 7256 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 7257 7258 Output Parameter: 7259 . submat - the array of submatrices 7260 7261 Level: advanced 7262 7263 Note: 7264 This is used by `PCGASM` 7265 7266 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse` 7267 @*/ 7268 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) 7269 { 7270 PetscInt i; 7271 PetscBool eq; 7272 7273 PetscFunctionBegin; 7274 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7275 PetscValidType(mat, 1); 7276 if (n) { 7277 PetscAssertPointer(irow, 3); 7278 PetscValidHeaderSpecific(*irow, IS_CLASSID, 3); 7279 PetscAssertPointer(icol, 4); 7280 PetscValidHeaderSpecific(*icol, IS_CLASSID, 4); 7281 } 7282 PetscAssertPointer(submat, 6); 7283 if (n && scall == MAT_REUSE_MATRIX) { 7284 PetscAssertPointer(*submat, 6); 7285 PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6); 7286 } 7287 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7288 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7289 MatCheckPreallocated(mat, 1); 7290 7291 PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0)); 7292 PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat); 7293 PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0)); 7294 for (i = 0; i < n; i++) { 7295 PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq)); 7296 if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i])); 7297 } 7298 PetscFunctionReturn(PETSC_SUCCESS); 7299 } 7300 7301 /*@C 7302 MatDestroyMatrices - Destroys an array of matrices 7303 7304 Collective 7305 7306 Input Parameters: 7307 + n - the number of local matrices 7308 - mat - the matrices (this is a pointer to the array of matrices) 7309 7310 Level: advanced 7311 7312 Notes: 7313 Frees not only the matrices, but also the array that contains the matrices 7314 7315 For matrices obtained with `MatCreateSubMatrices()` use `MatDestroySubMatrices()` 7316 7317 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()` 7318 @*/ 7319 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) 7320 { 7321 PetscInt i; 7322 7323 PetscFunctionBegin; 7324 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7325 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7326 PetscAssertPointer(mat, 2); 7327 7328 for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i])); 7329 7330 /* memory is allocated even if n = 0 */ 7331 PetscCall(PetscFree(*mat)); 7332 PetscFunctionReturn(PETSC_SUCCESS); 7333 } 7334 7335 /*@C 7336 MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`. 7337 7338 Collective 7339 7340 Input Parameters: 7341 + n - the number of local matrices 7342 - mat - the matrices (this is a pointer to the array of matrices, to match the calling sequence of `MatCreateSubMatrices()`) 7343 7344 Level: advanced 7345 7346 Note: 7347 Frees not only the matrices, but also the array that contains the matrices 7348 7349 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7350 @*/ 7351 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) 7352 { 7353 Mat mat0; 7354 7355 PetscFunctionBegin; 7356 if (!*mat) PetscFunctionReturn(PETSC_SUCCESS); 7357 /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */ 7358 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n); 7359 PetscAssertPointer(mat, 2); 7360 7361 mat0 = (*mat)[0]; 7362 if (mat0 && mat0->ops->destroysubmatrices) { 7363 PetscCall((*mat0->ops->destroysubmatrices)(n, mat)); 7364 } else { 7365 PetscCall(MatDestroyMatrices(n, mat)); 7366 } 7367 PetscFunctionReturn(PETSC_SUCCESS); 7368 } 7369 7370 /*@ 7371 MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process 7372 7373 Collective 7374 7375 Input Parameter: 7376 . mat - the matrix 7377 7378 Output Parameter: 7379 . matstruct - the sequential matrix with the nonzero structure of `mat` 7380 7381 Level: developer 7382 7383 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()` 7384 @*/ 7385 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) 7386 { 7387 PetscFunctionBegin; 7388 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7389 PetscAssertPointer(matstruct, 2); 7390 7391 PetscValidType(mat, 1); 7392 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7393 MatCheckPreallocated(mat, 1); 7394 7395 PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7396 PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct); 7397 PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0)); 7398 PetscFunctionReturn(PETSC_SUCCESS); 7399 } 7400 7401 /*@C 7402 MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`. 7403 7404 Collective 7405 7406 Input Parameter: 7407 . mat - the matrix 7408 7409 Level: advanced 7410 7411 Note: 7412 This is not needed, one can just call `MatDestroy()` 7413 7414 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()` 7415 @*/ 7416 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) 7417 { 7418 PetscFunctionBegin; 7419 PetscAssertPointer(mat, 1); 7420 PetscCall(MatDestroy(mat)); 7421 PetscFunctionReturn(PETSC_SUCCESS); 7422 } 7423 7424 /*@ 7425 MatIncreaseOverlap - Given a set of submatrices indicated by index sets, 7426 replaces the index sets by larger ones that represent submatrices with 7427 additional overlap. 7428 7429 Collective 7430 7431 Input Parameters: 7432 + mat - the matrix 7433 . n - the number of index sets 7434 . is - the array of index sets (these index sets will changed during the call) 7435 - ov - the additional overlap requested 7436 7437 Options Database Key: 7438 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7439 7440 Level: developer 7441 7442 Note: 7443 The computed overlap preserves the matrix block sizes when the blocks are square. 7444 That is: if a matrix nonzero for a given block would increase the overlap all columns associated with 7445 that block are included in the overlap regardless of whether each specific column would increase the overlap. 7446 7447 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()` 7448 @*/ 7449 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) 7450 { 7451 PetscInt i, bs, cbs; 7452 7453 PetscFunctionBegin; 7454 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7455 PetscValidType(mat, 1); 7456 PetscValidLogicalCollectiveInt(mat, n, 2); 7457 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7458 if (n) { 7459 PetscAssertPointer(is, 3); 7460 for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3); 7461 } 7462 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7463 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7464 MatCheckPreallocated(mat, 1); 7465 7466 if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS); 7467 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7468 PetscUseTypeMethod(mat, increaseoverlap, n, is, ov); 7469 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7470 PetscCall(MatGetBlockSizes(mat, &bs, &cbs)); 7471 if (bs == cbs) { 7472 for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs)); 7473 } 7474 PetscFunctionReturn(PETSC_SUCCESS); 7475 } 7476 7477 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt); 7478 7479 /*@ 7480 MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across 7481 a sub communicator, replaces the index sets by larger ones that represent submatrices with 7482 additional overlap. 7483 7484 Collective 7485 7486 Input Parameters: 7487 + mat - the matrix 7488 . n - the number of index sets 7489 . is - the array of index sets (these index sets will changed during the call) 7490 - ov - the additional overlap requested 7491 7492 ` Options Database Key: 7493 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix) 7494 7495 Level: developer 7496 7497 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()` 7498 @*/ 7499 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) 7500 { 7501 PetscInt i; 7502 7503 PetscFunctionBegin; 7504 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7505 PetscValidType(mat, 1); 7506 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n); 7507 if (n) { 7508 PetscAssertPointer(is, 3); 7509 PetscValidHeaderSpecific(*is, IS_CLASSID, 3); 7510 } 7511 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 7512 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 7513 MatCheckPreallocated(mat, 1); 7514 if (!ov) PetscFunctionReturn(PETSC_SUCCESS); 7515 PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7516 for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov)); 7517 PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0)); 7518 PetscFunctionReturn(PETSC_SUCCESS); 7519 } 7520 7521 /*@ 7522 MatGetBlockSize - Returns the matrix block size. 7523 7524 Not Collective 7525 7526 Input Parameter: 7527 . mat - the matrix 7528 7529 Output Parameter: 7530 . bs - block size 7531 7532 Level: intermediate 7533 7534 Notes: 7535 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7536 7537 If the block size has not been set yet this routine returns 1. 7538 7539 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()` 7540 @*/ 7541 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) 7542 { 7543 PetscFunctionBegin; 7544 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7545 PetscAssertPointer(bs, 2); 7546 *bs = mat->rmap->bs; 7547 PetscFunctionReturn(PETSC_SUCCESS); 7548 } 7549 7550 /*@ 7551 MatGetBlockSizes - Returns the matrix block row and column sizes. 7552 7553 Not Collective 7554 7555 Input Parameter: 7556 . mat - the matrix 7557 7558 Output Parameters: 7559 + rbs - row block size 7560 - cbs - column block size 7561 7562 Level: intermediate 7563 7564 Notes: 7565 Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix. 7566 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 7567 7568 If a block size has not been set yet this routine returns 1. 7569 7570 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()` 7571 @*/ 7572 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) 7573 { 7574 PetscFunctionBegin; 7575 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7576 if (rbs) PetscAssertPointer(rbs, 2); 7577 if (cbs) PetscAssertPointer(cbs, 3); 7578 if (rbs) *rbs = mat->rmap->bs; 7579 if (cbs) *cbs = mat->cmap->bs; 7580 PetscFunctionReturn(PETSC_SUCCESS); 7581 } 7582 7583 /*@ 7584 MatSetBlockSize - Sets the matrix block size. 7585 7586 Logically Collective 7587 7588 Input Parameters: 7589 + mat - the matrix 7590 - bs - block size 7591 7592 Level: intermediate 7593 7594 Notes: 7595 Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix. 7596 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 7597 7598 For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size 7599 is compatible with the matrix local sizes. 7600 7601 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()` 7602 @*/ 7603 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) 7604 { 7605 PetscFunctionBegin; 7606 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7607 PetscValidLogicalCollectiveInt(mat, bs, 2); 7608 PetscCall(MatSetBlockSizes(mat, bs, bs)); 7609 PetscFunctionReturn(PETSC_SUCCESS); 7610 } 7611 7612 typedef struct { 7613 PetscInt n; 7614 IS *is; 7615 Mat *mat; 7616 PetscObjectState nonzerostate; 7617 Mat C; 7618 } EnvelopeData; 7619 7620 static PetscErrorCode EnvelopeDataDestroy(void **ptr) 7621 { 7622 EnvelopeData *edata = (EnvelopeData *)*ptr; 7623 7624 PetscFunctionBegin; 7625 for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i])); 7626 PetscCall(PetscFree(edata->is)); 7627 PetscCall(PetscFree(edata)); 7628 PetscFunctionReturn(PETSC_SUCCESS); 7629 } 7630 7631 /*@ 7632 MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores 7633 the sizes of these blocks in the matrix. An individual block may lie over several processes. 7634 7635 Collective 7636 7637 Input Parameter: 7638 . mat - the matrix 7639 7640 Level: intermediate 7641 7642 Notes: 7643 There can be zeros within the blocks 7644 7645 The blocks can overlap between processes, including laying on more than two processes 7646 7647 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()` 7648 @*/ 7649 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) 7650 { 7651 PetscInt n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend; 7652 PetscInt *diag, *odiag, sc; 7653 VecScatter scatter; 7654 PetscScalar *seqv; 7655 const PetscScalar *parv; 7656 const PetscInt *ia, *ja; 7657 PetscBool set, flag, done; 7658 Mat AA = mat, A; 7659 MPI_Comm comm; 7660 PetscMPIInt rank, size, tag; 7661 MPI_Status status; 7662 PetscContainer container; 7663 EnvelopeData *edata; 7664 Vec seq, par; 7665 IS isglobal; 7666 7667 PetscFunctionBegin; 7668 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7669 PetscCall(MatIsSymmetricKnown(mat, &set, &flag)); 7670 if (!set || !flag) { 7671 /* TODO: only needs nonzero structure of transpose */ 7672 PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA)); 7673 PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN)); 7674 } 7675 PetscCall(MatAIJGetLocalMat(AA, &A)); 7676 PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7677 PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix"); 7678 7679 PetscCall(MatGetLocalSize(mat, &n, NULL)); 7680 PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag)); 7681 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 7682 PetscCallMPI(MPI_Comm_size(comm, &size)); 7683 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7684 7685 PetscCall(PetscMalloc2(n, &sizes, n, &starts)); 7686 7687 if (rank > 0) { 7688 PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7689 PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status)); 7690 } 7691 PetscCall(MatGetOwnershipRange(mat, &rstart, NULL)); 7692 for (i = 0; i < n; i++) { 7693 env = PetscMax(env, ja[ia[i + 1] - 1]); 7694 II = rstart + i; 7695 if (env == II) { 7696 starts[lblocks] = tbs; 7697 sizes[lblocks++] = 1 + II - tbs; 7698 tbs = 1 + II; 7699 } 7700 } 7701 if (rank < size - 1) { 7702 PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm)); 7703 PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm)); 7704 } 7705 7706 PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done)); 7707 if (!set || !flag) PetscCall(MatDestroy(&AA)); 7708 PetscCall(MatDestroy(&A)); 7709 7710 PetscCall(PetscNew(&edata)); 7711 PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate)); 7712 edata->n = lblocks; 7713 /* create IS needed for extracting blocks from the original matrix */ 7714 PetscCall(PetscMalloc1(lblocks, &edata->is)); 7715 for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i])); 7716 7717 /* Create the resulting inverse matrix nonzero structure with preallocation information */ 7718 PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C)); 7719 PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N)); 7720 PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat)); 7721 PetscCall(MatSetType(edata->C, MATAIJ)); 7722 7723 /* Communicate the start and end of each row, from each block to the correct rank */ 7724 /* TODO: Use PetscSF instead of VecScatter */ 7725 for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i]; 7726 PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq)); 7727 PetscCall(VecGetArrayWrite(seq, &seqv)); 7728 for (PetscInt i = 0; i < lblocks; i++) { 7729 for (PetscInt j = 0; j < sizes[i]; j++) { 7730 seqv[cnt] = starts[i]; 7731 seqv[cnt + 1] = starts[i] + sizes[i]; 7732 cnt += 2; 7733 } 7734 } 7735 PetscCall(VecRestoreArrayWrite(seq, &seqv)); 7736 PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat))); 7737 sc -= cnt; 7738 PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par)); 7739 PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal)); 7740 PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter)); 7741 PetscCall(ISDestroy(&isglobal)); 7742 PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7743 PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD)); 7744 PetscCall(VecScatterDestroy(&scatter)); 7745 PetscCall(VecDestroy(&seq)); 7746 PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend)); 7747 PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag)); 7748 PetscCall(VecGetArrayRead(par, &parv)); 7749 cnt = 0; 7750 PetscCall(MatGetSize(mat, NULL, &n)); 7751 for (PetscInt i = 0; i < mat->rmap->n; i++) { 7752 PetscInt start, end, d = 0, od = 0; 7753 7754 start = (PetscInt)PetscRealPart(parv[cnt]); 7755 end = (PetscInt)PetscRealPart(parv[cnt + 1]); 7756 cnt += 2; 7757 7758 if (start < cstart) { 7759 od += cstart - start + n - cend; 7760 d += cend - cstart; 7761 } else if (start < cend) { 7762 od += n - cend; 7763 d += cend - start; 7764 } else od += n - start; 7765 if (end <= cstart) { 7766 od -= cstart - end + n - cend; 7767 d -= cend - cstart; 7768 } else if (end < cend) { 7769 od -= n - cend; 7770 d -= cend - end; 7771 } else od -= n - end; 7772 7773 odiag[i] = od; 7774 diag[i] = d; 7775 } 7776 PetscCall(VecRestoreArrayRead(par, &parv)); 7777 PetscCall(VecDestroy(&par)); 7778 PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL)); 7779 PetscCall(PetscFree2(diag, odiag)); 7780 PetscCall(PetscFree2(sizes, starts)); 7781 7782 PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container)); 7783 PetscCall(PetscContainerSetPointer(container, edata)); 7784 PetscCall(PetscContainerSetCtxDestroy(container, EnvelopeDataDestroy)); 7785 PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container)); 7786 PetscCall(PetscObjectDereference((PetscObject)container)); 7787 PetscFunctionReturn(PETSC_SUCCESS); 7788 } 7789 7790 /*@ 7791 MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A 7792 7793 Collective 7794 7795 Input Parameters: 7796 + A - the matrix 7797 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine 7798 7799 Output Parameter: 7800 . C - matrix with inverted block diagonal of `A` 7801 7802 Level: advanced 7803 7804 Note: 7805 For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal. 7806 7807 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()` 7808 @*/ 7809 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) 7810 { 7811 PetscContainer container; 7812 EnvelopeData *edata; 7813 PetscObjectState nonzerostate; 7814 7815 PetscFunctionBegin; 7816 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7817 if (!container) { 7818 PetscCall(MatComputeVariableBlockEnvelope(A)); 7819 PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container)); 7820 } 7821 PetscCall(PetscContainerGetPointer(container, (void **)&edata)); 7822 PetscCall(MatGetNonzeroState(A, &nonzerostate)); 7823 PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure"); 7824 PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output"); 7825 7826 PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat)); 7827 *C = edata->C; 7828 7829 for (PetscInt i = 0; i < edata->n; i++) { 7830 Mat D; 7831 PetscScalar *dvalues; 7832 7833 PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D)); 7834 PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE)); 7835 PetscCall(MatSeqDenseInvert(D)); 7836 PetscCall(MatDenseGetArray(D, &dvalues)); 7837 PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES)); 7838 PetscCall(MatDestroy(&D)); 7839 } 7840 PetscCall(MatDestroySubMatrices(edata->n, &edata->mat)); 7841 PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY)); 7842 PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY)); 7843 PetscFunctionReturn(PETSC_SUCCESS); 7844 } 7845 7846 /*@ 7847 MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size 7848 7849 Not Collective 7850 7851 Input Parameters: 7852 + mat - the matrix 7853 . nblocks - the number of blocks on this process, each block can only exist on a single process 7854 - bsizes - the block sizes 7855 7856 Level: intermediate 7857 7858 Notes: 7859 Currently used by `PCVPBJACOBI` for `MATAIJ` matrices 7860 7861 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. 7862 7863 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, 7864 `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI` 7865 @*/ 7866 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[]) 7867 { 7868 PetscInt ncnt = 0, nlocal; 7869 7870 PetscFunctionBegin; 7871 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7872 PetscCall(MatGetLocalSize(mat, &nlocal, NULL)); 7873 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); 7874 for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i]; 7875 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); 7876 PetscCall(PetscFree(mat->bsizes)); 7877 mat->nblocks = nblocks; 7878 PetscCall(PetscMalloc1(nblocks, &mat->bsizes)); 7879 PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks)); 7880 PetscFunctionReturn(PETSC_SUCCESS); 7881 } 7882 7883 /*@C 7884 MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size 7885 7886 Not Collective; No Fortran Support 7887 7888 Input Parameter: 7889 . mat - the matrix 7890 7891 Output Parameters: 7892 + nblocks - the number of blocks on this process 7893 - bsizes - the block sizes 7894 7895 Level: intermediate 7896 7897 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7898 @*/ 7899 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[]) 7900 { 7901 PetscFunctionBegin; 7902 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 7903 if (nblocks) *nblocks = mat->nblocks; 7904 if (bsizes) *bsizes = mat->bsizes; 7905 PetscFunctionReturn(PETSC_SUCCESS); 7906 } 7907 7908 /*@ 7909 MatSelectVariableBlockSizes - When creating a submatrix, pass on the variable block sizes 7910 7911 Not Collective 7912 7913 Input Parameter: 7914 + subA - the submatrix 7915 . A - the original matrix 7916 - isrow - The `IS` of selected rows for the submatrix, must be sorted 7917 7918 Level: developer 7919 7920 Notes: 7921 If the index set is not sorted or contains off-process entries, this function will do nothing. 7922 7923 .seealso: [](ch_matrices), `Mat`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()` 7924 @*/ 7925 PetscErrorCode MatSelectVariableBlockSizes(Mat subA, Mat A, IS isrow) 7926 { 7927 const PetscInt *rows; 7928 PetscInt n, rStart, rEnd, Nb = 0; 7929 PetscBool flg = A->bsizes ? PETSC_TRUE : PETSC_FALSE; 7930 7931 PetscFunctionBegin; 7932 // The code for block size extraction does not support an unsorted IS 7933 if (flg) PetscCall(ISSorted(isrow, &flg)); 7934 // We don't support originally off-diagonal blocks 7935 if (flg) { 7936 PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd)); 7937 PetscCall(ISGetLocalSize(isrow, &n)); 7938 PetscCall(ISGetIndices(isrow, &rows)); 7939 for (PetscInt i = 0; i < n && flg; ++i) { 7940 if (rows[i] < rStart || rows[i] >= rEnd) flg = PETSC_FALSE; 7941 } 7942 PetscCall(ISRestoreIndices(isrow, &rows)); 7943 } 7944 // quiet return if we can't extract block size 7945 PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &flg, 1, MPI_C_BOOL, MPI_LAND, PetscObjectComm((PetscObject)subA))); 7946 if (!flg) PetscFunctionReturn(PETSC_SUCCESS); 7947 7948 // extract block sizes 7949 PetscCall(ISGetIndices(isrow, &rows)); 7950 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7951 PetscBool occupied = PETSC_FALSE; 7952 7953 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7954 const PetscInt row = gr + br; 7955 7956 if (i == n) break; 7957 if (rows[i] == row) { 7958 occupied = PETSC_TRUE; 7959 ++i; 7960 } 7961 while (i < n && rows[i] < row) ++i; 7962 } 7963 gr += A->bsizes[b]; 7964 if (occupied) ++Nb; 7965 } 7966 subA->nblocks = Nb; 7967 PetscCall(PetscFree(subA->bsizes)); 7968 PetscCall(PetscMalloc1(subA->nblocks, &subA->bsizes)); 7969 PetscInt sb = 0; 7970 for (PetscInt b = 0, gr = rStart, i = 0; b < A->nblocks; ++b) { 7971 if (sb < subA->nblocks) subA->bsizes[sb] = 0; 7972 for (PetscInt br = 0; br < A->bsizes[b]; ++br) { 7973 const PetscInt row = gr + br; 7974 7975 if (i == n) break; 7976 if (rows[i] == row) { 7977 ++subA->bsizes[sb]; 7978 ++i; 7979 } 7980 while (i < n && rows[i] < row) ++i; 7981 } 7982 gr += A->bsizes[b]; 7983 if (sb < subA->nblocks && subA->bsizes[sb]) ++sb; 7984 } 7985 PetscCheck(sb == subA->nblocks, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid number of blocks %" PetscInt_FMT " != %" PetscInt_FMT, sb, subA->nblocks); 7986 PetscInt nlocal, ncnt = 0; 7987 PetscCall(MatGetLocalSize(subA, &nlocal, NULL)); 7988 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); 7989 for (PetscInt i = 0; i < subA->nblocks; i++) ncnt += subA->bsizes[i]; 7990 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); 7991 PetscCall(ISRestoreIndices(isrow, &rows)); 7992 PetscFunctionReturn(PETSC_SUCCESS); 7993 } 7994 7995 /*@ 7996 MatSetBlockSizes - Sets the matrix block row and column sizes. 7997 7998 Logically Collective 7999 8000 Input Parameters: 8001 + mat - the matrix 8002 . rbs - row block size 8003 - cbs - column block size 8004 8005 Level: intermediate 8006 8007 Notes: 8008 Block row formats are `MATBAIJ` and `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix. 8009 If you pass a different block size for the columns than the rows, the row block size determines the square block storage. 8010 This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later. 8011 8012 For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes 8013 are compatible with the matrix local sizes. 8014 8015 The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`. 8016 8017 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()` 8018 @*/ 8019 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) 8020 { 8021 PetscFunctionBegin; 8022 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8023 PetscValidLogicalCollectiveInt(mat, rbs, 2); 8024 PetscValidLogicalCollectiveInt(mat, cbs, 3); 8025 PetscTryTypeMethod(mat, setblocksizes, rbs, cbs); 8026 if (mat->rmap->refcnt) { 8027 ISLocalToGlobalMapping l2g = NULL; 8028 PetscLayout nmap = NULL; 8029 8030 PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap)); 8031 if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g)); 8032 PetscCall(PetscLayoutDestroy(&mat->rmap)); 8033 mat->rmap = nmap; 8034 mat->rmap->mapping = l2g; 8035 } 8036 if (mat->cmap->refcnt) { 8037 ISLocalToGlobalMapping l2g = NULL; 8038 PetscLayout nmap = NULL; 8039 8040 PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap)); 8041 if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g)); 8042 PetscCall(PetscLayoutDestroy(&mat->cmap)); 8043 mat->cmap = nmap; 8044 mat->cmap->mapping = l2g; 8045 } 8046 PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs)); 8047 PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs)); 8048 PetscFunctionReturn(PETSC_SUCCESS); 8049 } 8050 8051 /*@ 8052 MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices 8053 8054 Logically Collective 8055 8056 Input Parameters: 8057 + mat - the matrix 8058 . fromRow - matrix from which to copy row block size 8059 - fromCol - matrix from which to copy column block size (can be same as fromRow) 8060 8061 Level: developer 8062 8063 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()` 8064 @*/ 8065 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) 8066 { 8067 PetscFunctionBegin; 8068 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8069 PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2); 8070 PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3); 8071 PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs)); 8072 PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs)); 8073 PetscFunctionReturn(PETSC_SUCCESS); 8074 } 8075 8076 /*@ 8077 MatResidual - Default routine to calculate the residual r = b - Ax 8078 8079 Collective 8080 8081 Input Parameters: 8082 + mat - the matrix 8083 . b - the right-hand-side 8084 - x - the approximate solution 8085 8086 Output Parameter: 8087 . r - location to store the residual 8088 8089 Level: developer 8090 8091 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()` 8092 @*/ 8093 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) 8094 { 8095 PetscFunctionBegin; 8096 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8097 PetscValidHeaderSpecific(b, VEC_CLASSID, 2); 8098 PetscValidHeaderSpecific(x, VEC_CLASSID, 3); 8099 PetscValidHeaderSpecific(r, VEC_CLASSID, 4); 8100 PetscValidType(mat, 1); 8101 MatCheckPreallocated(mat, 1); 8102 PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0)); 8103 if (!mat->ops->residual) { 8104 PetscCall(MatMult(mat, x, r)); 8105 PetscCall(VecAYPX(r, -1.0, b)); 8106 } else { 8107 PetscUseTypeMethod(mat, residual, b, x, r); 8108 } 8109 PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0)); 8110 PetscFunctionReturn(PETSC_SUCCESS); 8111 } 8112 8113 /*@C 8114 MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix 8115 8116 Collective 8117 8118 Input Parameters: 8119 + mat - the matrix 8120 . shift - 0 or 1 indicating we want the indices starting at 0 or 1 8121 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8122 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8123 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8124 always used. 8125 8126 Output Parameters: 8127 + n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed 8128 . 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 8129 . ja - the column indices, use `NULL` if not needed 8130 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers 8131 are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set 8132 8133 Level: developer 8134 8135 Notes: 8136 You CANNOT change any of the ia[] or ja[] values. 8137 8138 Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values. 8139 8140 Fortran Notes: 8141 Use 8142 .vb 8143 PetscInt, pointer :: ia(:),ja(:) 8144 call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr) 8145 ! Access the ith and jth entries via ia(i) and ja(j) 8146 .ve 8147 8148 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()` 8149 @*/ 8150 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8151 { 8152 PetscFunctionBegin; 8153 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8154 PetscValidType(mat, 1); 8155 if (n) PetscAssertPointer(n, 5); 8156 if (ia) PetscAssertPointer(ia, 6); 8157 if (ja) PetscAssertPointer(ja, 7); 8158 if (done) PetscAssertPointer(done, 8); 8159 MatCheckPreallocated(mat, 1); 8160 if (!mat->ops->getrowij && done) *done = PETSC_FALSE; 8161 else { 8162 if (done) *done = PETSC_TRUE; 8163 PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0)); 8164 PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8165 PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0)); 8166 } 8167 PetscFunctionReturn(PETSC_SUCCESS); 8168 } 8169 8170 /*@C 8171 MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices. 8172 8173 Collective 8174 8175 Input Parameters: 8176 + mat - the matrix 8177 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8178 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be 8179 symmetrized 8180 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8181 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8182 always used. 8183 8184 Output Parameters: 8185 + n - number of columns in the (possibly compressed) matrix 8186 . ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix 8187 . ja - the row indices 8188 - done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned 8189 8190 Level: developer 8191 8192 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8193 @*/ 8194 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8195 { 8196 PetscFunctionBegin; 8197 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8198 PetscValidType(mat, 1); 8199 PetscAssertPointer(n, 5); 8200 if (ia) PetscAssertPointer(ia, 6); 8201 if (ja) PetscAssertPointer(ja, 7); 8202 PetscAssertPointer(done, 8); 8203 MatCheckPreallocated(mat, 1); 8204 if (!mat->ops->getcolumnij) *done = PETSC_FALSE; 8205 else { 8206 *done = PETSC_TRUE; 8207 PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8208 } 8209 PetscFunctionReturn(PETSC_SUCCESS); 8210 } 8211 8212 /*@C 8213 MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`. 8214 8215 Collective 8216 8217 Input Parameters: 8218 + mat - the matrix 8219 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8220 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8221 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8222 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8223 always used. 8224 . n - size of (possibly compressed) matrix 8225 . ia - the row pointers 8226 - ja - the column indices 8227 8228 Output Parameter: 8229 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8230 8231 Level: developer 8232 8233 Note: 8234 This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental 8235 us of the array after it has been restored. If you pass `NULL`, it will 8236 not zero the pointers. Use of ia or ja after `MatRestoreRowIJ()` is invalid. 8237 8238 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()` 8239 @*/ 8240 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8241 { 8242 PetscFunctionBegin; 8243 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8244 PetscValidType(mat, 1); 8245 if (ia) PetscAssertPointer(ia, 6); 8246 if (ja) PetscAssertPointer(ja, 7); 8247 if (done) PetscAssertPointer(done, 8); 8248 MatCheckPreallocated(mat, 1); 8249 8250 if (!mat->ops->restorerowij && done) *done = PETSC_FALSE; 8251 else { 8252 if (done) *done = PETSC_TRUE; 8253 PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done); 8254 if (n) *n = 0; 8255 if (ia) *ia = NULL; 8256 if (ja) *ja = NULL; 8257 } 8258 PetscFunctionReturn(PETSC_SUCCESS); 8259 } 8260 8261 /*@C 8262 MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`. 8263 8264 Collective 8265 8266 Input Parameters: 8267 + mat - the matrix 8268 . shift - 1 or zero indicating we want the indices starting at 0 or 1 8269 . symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized 8270 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the 8271 inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is 8272 always used. 8273 8274 Output Parameters: 8275 + n - size of (possibly compressed) matrix 8276 . ia - the column pointers 8277 . ja - the row indices 8278 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned 8279 8280 Level: developer 8281 8282 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()` 8283 @*/ 8284 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) 8285 { 8286 PetscFunctionBegin; 8287 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8288 PetscValidType(mat, 1); 8289 if (ia) PetscAssertPointer(ia, 6); 8290 if (ja) PetscAssertPointer(ja, 7); 8291 PetscAssertPointer(done, 8); 8292 MatCheckPreallocated(mat, 1); 8293 8294 if (!mat->ops->restorecolumnij) *done = PETSC_FALSE; 8295 else { 8296 *done = PETSC_TRUE; 8297 PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done); 8298 if (n) *n = 0; 8299 if (ia) *ia = NULL; 8300 if (ja) *ja = NULL; 8301 } 8302 PetscFunctionReturn(PETSC_SUCCESS); 8303 } 8304 8305 /*@ 8306 MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or 8307 `MatGetColumnIJ()`. 8308 8309 Collective 8310 8311 Input Parameters: 8312 + mat - the matrix 8313 . ncolors - maximum color value 8314 . n - number of entries in colorarray 8315 - colorarray - array indicating color for each column 8316 8317 Output Parameter: 8318 . iscoloring - coloring generated using colorarray information 8319 8320 Level: developer 8321 8322 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()` 8323 @*/ 8324 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) 8325 { 8326 PetscFunctionBegin; 8327 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8328 PetscValidType(mat, 1); 8329 PetscAssertPointer(colorarray, 4); 8330 PetscAssertPointer(iscoloring, 5); 8331 MatCheckPreallocated(mat, 1); 8332 8333 if (!mat->ops->coloringpatch) { 8334 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring)); 8335 } else { 8336 PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring); 8337 } 8338 PetscFunctionReturn(PETSC_SUCCESS); 8339 } 8340 8341 /*@ 8342 MatSetUnfactored - Resets a factored matrix to be treated as unfactored. 8343 8344 Logically Collective 8345 8346 Input Parameter: 8347 . mat - the factored matrix to be reset 8348 8349 Level: developer 8350 8351 Notes: 8352 This routine should be used only with factored matrices formed by in-place 8353 factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE` 8354 format). This option can save memory, for example, when solving nonlinear 8355 systems with a matrix-free Newton-Krylov method and a matrix-based, in-place 8356 ILU(0) preconditioner. 8357 8358 One can specify in-place ILU(0) factorization by calling 8359 .vb 8360 PCType(pc,PCILU); 8361 PCFactorSeUseInPlace(pc); 8362 .ve 8363 or by using the options -pc_type ilu -pc_factor_in_place 8364 8365 In-place factorization ILU(0) can also be used as a local 8366 solver for the blocks within the block Jacobi or additive Schwarz 8367 methods (runtime option: -sub_pc_factor_in_place). See Users-Manual: ch_pc 8368 for details on setting local solver options. 8369 8370 Most users should employ the `KSP` interface for linear solvers 8371 instead of working directly with matrix algebra routines such as this. 8372 See, e.g., `KSPCreate()`. 8373 8374 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()` 8375 @*/ 8376 PetscErrorCode MatSetUnfactored(Mat mat) 8377 { 8378 PetscFunctionBegin; 8379 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8380 PetscValidType(mat, 1); 8381 MatCheckPreallocated(mat, 1); 8382 mat->factortype = MAT_FACTOR_NONE; 8383 if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS); 8384 PetscUseTypeMethod(mat, setunfactored); 8385 PetscFunctionReturn(PETSC_SUCCESS); 8386 } 8387 8388 /*@ 8389 MatCreateSubMatrix - Gets a single submatrix on the same number of processors 8390 as the original matrix. 8391 8392 Collective 8393 8394 Input Parameters: 8395 + mat - the original matrix 8396 . isrow - parallel `IS` containing the rows this processor should obtain 8397 . 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. 8398 - cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 8399 8400 Output Parameter: 8401 . newmat - the new submatrix, of the same type as the original matrix 8402 8403 Level: advanced 8404 8405 Notes: 8406 The submatrix will be able to be multiplied with vectors using the same layout as `iscol`. 8407 8408 Some matrix types place restrictions on the row and column indices, such 8409 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; 8410 for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row. 8411 8412 The index sets may not have duplicate entries. 8413 8414 The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`, 8415 the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls 8416 to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX` 8417 will reuse the matrix generated the first time. You should call `MatDestroy()` on `newmat` when 8418 you are finished using it. 8419 8420 The communicator of the newly obtained matrix is ALWAYS the same as the communicator of 8421 the input matrix. 8422 8423 If `iscol` is `NULL` then all columns are obtained (not supported in Fortran). 8424 8425 If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature 8426 is used by `PCFIELDSPLIT` to allow easy nesting of its use. 8427 8428 Example usage: 8429 Consider the following 8x8 matrix with 34 non-zero values, that is 8430 assembled across 3 processors. Let's assume that proc0 owns 3 rows, 8431 proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 8432 as follows 8433 .vb 8434 1 2 0 | 0 3 0 | 0 4 8435 Proc0 0 5 6 | 7 0 0 | 8 0 8436 9 0 10 | 11 0 0 | 12 0 8437 ------------------------------------- 8438 13 0 14 | 15 16 17 | 0 0 8439 Proc1 0 18 0 | 19 20 21 | 0 0 8440 0 0 0 | 22 23 0 | 24 0 8441 ------------------------------------- 8442 Proc2 25 26 27 | 0 0 28 | 29 0 8443 30 0 0 | 31 32 33 | 0 34 8444 .ve 8445 8446 Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6]. The resulting submatrix is 8447 8448 .vb 8449 2 0 | 0 3 0 | 0 8450 Proc0 5 6 | 7 0 0 | 8 8451 ------------------------------- 8452 Proc1 18 0 | 19 20 21 | 0 8453 ------------------------------- 8454 Proc2 26 27 | 0 0 28 | 29 8455 0 0 | 31 32 33 | 0 8456 .ve 8457 8458 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()` 8459 @*/ 8460 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) 8461 { 8462 PetscMPIInt size; 8463 Mat *local; 8464 IS iscoltmp; 8465 PetscBool flg; 8466 8467 PetscFunctionBegin; 8468 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8469 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 8470 if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 8471 PetscAssertPointer(newmat, 5); 8472 if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5); 8473 PetscValidType(mat, 1); 8474 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 8475 PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX"); 8476 8477 MatCheckPreallocated(mat, 1); 8478 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 8479 8480 if (!iscol || isrow == iscol) { 8481 PetscBool stride; 8482 PetscMPIInt grabentirematrix = 0, grab; 8483 PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride)); 8484 if (stride) { 8485 PetscInt first, step, n, rstart, rend; 8486 PetscCall(ISStrideGetInfo(isrow, &first, &step)); 8487 if (step == 1) { 8488 PetscCall(MatGetOwnershipRange(mat, &rstart, &rend)); 8489 if (rstart == first) { 8490 PetscCall(ISGetLocalSize(isrow, &n)); 8491 if (n == rend - rstart) grabentirematrix = 1; 8492 } 8493 } 8494 } 8495 PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat))); 8496 if (grab) { 8497 PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n")); 8498 if (cll == MAT_INITIAL_MATRIX) { 8499 *newmat = mat; 8500 PetscCall(PetscObjectReference((PetscObject)mat)); 8501 } 8502 PetscFunctionReturn(PETSC_SUCCESS); 8503 } 8504 } 8505 8506 if (!iscol) { 8507 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp)); 8508 } else { 8509 iscoltmp = iscol; 8510 } 8511 8512 /* if original matrix is on just one processor then use submatrix generated */ 8513 if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) { 8514 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat)); 8515 goto setproperties; 8516 } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) { 8517 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local)); 8518 *newmat = *local; 8519 PetscCall(PetscFree(local)); 8520 goto setproperties; 8521 } else if (!mat->ops->createsubmatrix) { 8522 /* Create a new matrix type that implements the operation using the full matrix */ 8523 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8524 switch (cll) { 8525 case MAT_INITIAL_MATRIX: 8526 PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); 8527 break; 8528 case MAT_REUSE_MATRIX: 8529 PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); 8530 break; 8531 default: 8532 SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX"); 8533 } 8534 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8535 goto setproperties; 8536 } 8537 8538 PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0)); 8539 PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat); 8540 PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0)); 8541 8542 setproperties: 8543 if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) { 8544 PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg)); 8545 if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat)); 8546 } 8547 if (!iscol) PetscCall(ISDestroy(&iscoltmp)); 8548 if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat)); 8549 if (!iscol || isrow == iscol) PetscCall(MatSelectVariableBlockSizes(*newmat, mat, isrow)); 8550 PetscFunctionReturn(PETSC_SUCCESS); 8551 } 8552 8553 /*@ 8554 MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix 8555 8556 Not Collective 8557 8558 Input Parameters: 8559 + A - the matrix we wish to propagate options from 8560 - B - the matrix we wish to propagate options to 8561 8562 Level: beginner 8563 8564 Note: 8565 Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL` 8566 8567 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()` 8568 @*/ 8569 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) 8570 { 8571 PetscFunctionBegin; 8572 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8573 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 8574 B->symmetry_eternal = A->symmetry_eternal; 8575 B->structural_symmetry_eternal = A->structural_symmetry_eternal; 8576 B->symmetric = A->symmetric; 8577 B->structurally_symmetric = A->structurally_symmetric; 8578 B->spd = A->spd; 8579 B->hermitian = A->hermitian; 8580 PetscFunctionReturn(PETSC_SUCCESS); 8581 } 8582 8583 /*@ 8584 MatStashSetInitialSize - sets the sizes of the matrix stash, that is 8585 used during the assembly process to store values that belong to 8586 other processors. 8587 8588 Not Collective 8589 8590 Input Parameters: 8591 + mat - the matrix 8592 . size - the initial size of the stash. 8593 - bsize - the initial size of the block-stash(if used). 8594 8595 Options Database Keys: 8596 + -matstash_initial_size <size> or <size0,size1,...sizep-1> - set initial size 8597 - -matstash_block_initial_size <bsize> or <bsize0,bsize1,...bsizep-1> - set initial block size 8598 8599 Level: intermediate 8600 8601 Notes: 8602 The block-stash is used for values set with `MatSetValuesBlocked()` while 8603 the stash is used for values set with `MatSetValues()` 8604 8605 Run with the option -info and look for output of the form 8606 MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs. 8607 to determine the appropriate value, MM, to use for size and 8608 MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs. 8609 to determine the value, BMM to use for bsize 8610 8611 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()` 8612 @*/ 8613 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) 8614 { 8615 PetscFunctionBegin; 8616 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8617 PetscValidType(mat, 1); 8618 PetscCall(MatStashSetInitialSize_Private(&mat->stash, size)); 8619 PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize)); 8620 PetscFunctionReturn(PETSC_SUCCESS); 8621 } 8622 8623 /*@ 8624 MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of 8625 the matrix 8626 8627 Neighbor-wise Collective 8628 8629 Input Parameters: 8630 + A - the matrix 8631 . x - the vector to be multiplied by the interpolation operator 8632 - y - the vector to be added to the result 8633 8634 Output Parameter: 8635 . w - the resulting vector 8636 8637 Level: intermediate 8638 8639 Notes: 8640 `w` may be the same vector as `y`. 8641 8642 This allows one to use either the restriction or interpolation (its transpose) 8643 matrix to do the interpolation 8644 8645 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8646 @*/ 8647 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) 8648 { 8649 PetscInt M, N, Ny; 8650 8651 PetscFunctionBegin; 8652 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8653 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8654 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8655 PetscValidHeaderSpecific(w, VEC_CLASSID, 4); 8656 PetscCall(MatGetSize(A, &M, &N)); 8657 PetscCall(VecGetSize(y, &Ny)); 8658 if (M == Ny) { 8659 PetscCall(MatMultAdd(A, x, y, w)); 8660 } else { 8661 PetscCall(MatMultTransposeAdd(A, x, y, w)); 8662 } 8663 PetscFunctionReturn(PETSC_SUCCESS); 8664 } 8665 8666 /*@ 8667 MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of 8668 the matrix 8669 8670 Neighbor-wise Collective 8671 8672 Input Parameters: 8673 + A - the matrix 8674 - x - the vector to be interpolated 8675 8676 Output Parameter: 8677 . y - the resulting vector 8678 8679 Level: intermediate 8680 8681 Note: 8682 This allows one to use either the restriction or interpolation (its transpose) 8683 matrix to do the interpolation 8684 8685 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG` 8686 @*/ 8687 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) 8688 { 8689 PetscInt M, N, Ny; 8690 8691 PetscFunctionBegin; 8692 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8693 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8694 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8695 PetscCall(MatGetSize(A, &M, &N)); 8696 PetscCall(VecGetSize(y, &Ny)); 8697 if (M == Ny) { 8698 PetscCall(MatMult(A, x, y)); 8699 } else { 8700 PetscCall(MatMultTranspose(A, x, y)); 8701 } 8702 PetscFunctionReturn(PETSC_SUCCESS); 8703 } 8704 8705 /*@ 8706 MatRestrict - $y = A*x$ or $A^T*x$ 8707 8708 Neighbor-wise Collective 8709 8710 Input Parameters: 8711 + A - the matrix 8712 - x - the vector to be restricted 8713 8714 Output Parameter: 8715 . y - the resulting vector 8716 8717 Level: intermediate 8718 8719 Note: 8720 This allows one to use either the restriction or interpolation (its transpose) 8721 matrix to do the restriction 8722 8723 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG` 8724 @*/ 8725 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) 8726 { 8727 PetscInt M, N, Nx; 8728 8729 PetscFunctionBegin; 8730 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8731 PetscValidHeaderSpecific(x, VEC_CLASSID, 2); 8732 PetscValidHeaderSpecific(y, VEC_CLASSID, 3); 8733 PetscCall(MatGetSize(A, &M, &N)); 8734 PetscCall(VecGetSize(x, &Nx)); 8735 if (M == Nx) { 8736 PetscCall(MatMultTranspose(A, x, y)); 8737 } else { 8738 PetscCall(MatMult(A, x, y)); 8739 } 8740 PetscFunctionReturn(PETSC_SUCCESS); 8741 } 8742 8743 /*@ 8744 MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A` 8745 8746 Neighbor-wise Collective 8747 8748 Input Parameters: 8749 + A - the matrix 8750 . x - the input dense matrix to be multiplied 8751 - w - the input dense matrix to be added to the result 8752 8753 Output Parameter: 8754 . y - the output dense matrix 8755 8756 Level: intermediate 8757 8758 Note: 8759 This allows one to use either the restriction or interpolation (its transpose) 8760 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8761 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8762 8763 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG` 8764 @*/ 8765 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) 8766 { 8767 PetscInt M, N, Mx, Nx, Mo, My = 0, Ny = 0; 8768 PetscBool trans = PETSC_TRUE; 8769 MatReuse reuse = MAT_INITIAL_MATRIX; 8770 8771 PetscFunctionBegin; 8772 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 8773 PetscValidHeaderSpecific(x, MAT_CLASSID, 2); 8774 PetscValidType(x, 2); 8775 if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3); 8776 if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4); 8777 PetscCall(MatGetSize(A, &M, &N)); 8778 PetscCall(MatGetSize(x, &Mx, &Nx)); 8779 if (N == Mx) trans = PETSC_FALSE; 8780 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); 8781 Mo = trans ? N : M; 8782 if (*y) { 8783 PetscCall(MatGetSize(*y, &My, &Ny)); 8784 if (Mo == My && Nx == Ny) { 8785 reuse = MAT_REUSE_MATRIX; 8786 } else { 8787 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); 8788 PetscCall(MatDestroy(y)); 8789 } 8790 } 8791 8792 if (w && *y == w) { /* this is to minimize changes in PCMG */ 8793 PetscBool flg; 8794 8795 PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w)); 8796 if (w) { 8797 PetscInt My, Ny, Mw, Nw; 8798 8799 PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg)); 8800 PetscCall(MatGetSize(*y, &My, &Ny)); 8801 PetscCall(MatGetSize(w, &Mw, &Nw)); 8802 if (!flg || My != Mw || Ny != Nw) w = NULL; 8803 } 8804 if (!w) { 8805 PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w)); 8806 PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w)); 8807 PetscCall(PetscObjectDereference((PetscObject)w)); 8808 } else { 8809 PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN)); 8810 } 8811 } 8812 if (!trans) { 8813 PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8814 } else { 8815 PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y)); 8816 } 8817 if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN)); 8818 PetscFunctionReturn(PETSC_SUCCESS); 8819 } 8820 8821 /*@ 8822 MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8823 8824 Neighbor-wise Collective 8825 8826 Input Parameters: 8827 + A - the matrix 8828 - x - the input dense matrix 8829 8830 Output Parameter: 8831 . y - the output dense matrix 8832 8833 Level: intermediate 8834 8835 Note: 8836 This allows one to use either the restriction or interpolation (its transpose) 8837 matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes, 8838 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8839 8840 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG` 8841 @*/ 8842 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) 8843 { 8844 PetscFunctionBegin; 8845 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8846 PetscFunctionReturn(PETSC_SUCCESS); 8847 } 8848 8849 /*@ 8850 MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A` 8851 8852 Neighbor-wise Collective 8853 8854 Input Parameters: 8855 + A - the matrix 8856 - x - the input dense matrix 8857 8858 Output Parameter: 8859 . y - the output dense matrix 8860 8861 Level: intermediate 8862 8863 Note: 8864 This allows one to use either the restriction or interpolation (its transpose) 8865 matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes, 8866 otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied. 8867 8868 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG` 8869 @*/ 8870 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) 8871 { 8872 PetscFunctionBegin; 8873 PetscCall(MatMatInterpolateAdd(A, x, NULL, y)); 8874 PetscFunctionReturn(PETSC_SUCCESS); 8875 } 8876 8877 /*@ 8878 MatGetNullSpace - retrieves the null space of a matrix. 8879 8880 Logically Collective 8881 8882 Input Parameters: 8883 + mat - the matrix 8884 - nullsp - the null space object 8885 8886 Level: developer 8887 8888 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace` 8889 @*/ 8890 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) 8891 { 8892 PetscFunctionBegin; 8893 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 8894 PetscAssertPointer(nullsp, 2); 8895 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp; 8896 PetscFunctionReturn(PETSC_SUCCESS); 8897 } 8898 8899 /*@C 8900 MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices 8901 8902 Logically Collective 8903 8904 Input Parameters: 8905 + n - the number of matrices 8906 - mat - the array of matrices 8907 8908 Output Parameters: 8909 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n` 8910 8911 Level: developer 8912 8913 Note: 8914 Call `MatRestoreNullspaces()` to provide these to another array of matrices 8915 8916 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8917 `MatNullSpaceRemove()`, `MatRestoreNullSpaces()` 8918 @*/ 8919 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8920 { 8921 PetscFunctionBegin; 8922 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8923 PetscAssertPointer(mat, 2); 8924 PetscAssertPointer(nullsp, 3); 8925 8926 PetscCall(PetscCalloc1(3 * n, nullsp)); 8927 for (PetscInt i = 0; i < n; i++) { 8928 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8929 (*nullsp)[i] = mat[i]->nullsp; 8930 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i])); 8931 (*nullsp)[n + i] = mat[i]->nearnullsp; 8932 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i])); 8933 (*nullsp)[2 * n + i] = mat[i]->transnullsp; 8934 PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i])); 8935 } 8936 PetscFunctionReturn(PETSC_SUCCESS); 8937 } 8938 8939 /*@C 8940 MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices 8941 8942 Logically Collective 8943 8944 Input Parameters: 8945 + n - the number of matrices 8946 . mat - the array of matrices 8947 - nullsp - an array of null spaces 8948 8949 Level: developer 8950 8951 Note: 8952 Call `MatGetNullSpaces()` to create `nullsp` 8953 8954 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, 8955 `MatNullSpaceRemove()`, `MatGetNullSpaces()` 8956 @*/ 8957 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[]) 8958 { 8959 PetscFunctionBegin; 8960 PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n); 8961 PetscAssertPointer(mat, 2); 8962 PetscAssertPointer(nullsp, 3); 8963 PetscAssertPointer(*nullsp, 3); 8964 8965 for (PetscInt i = 0; i < n; i++) { 8966 PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2); 8967 PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i])); 8968 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i])); 8969 PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i])); 8970 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i])); 8971 PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i])); 8972 PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i])); 8973 } 8974 PetscCall(PetscFree(*nullsp)); 8975 PetscFunctionReturn(PETSC_SUCCESS); 8976 } 8977 8978 /*@ 8979 MatSetNullSpace - attaches a null space to a matrix. 8980 8981 Logically Collective 8982 8983 Input Parameters: 8984 + mat - the matrix 8985 - nullsp - the null space object 8986 8987 Level: advanced 8988 8989 Notes: 8990 This null space is used by the `KSP` linear solvers to solve singular systems. 8991 8992 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` 8993 8994 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 8995 to zero but the linear system will still be solved in a least squares sense. 8996 8997 The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that 8998 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)$. 8999 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 9000 $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 9001 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)$. 9002 This $\hat{b}$ can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix. 9003 9004 If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one has called 9005 `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this 9006 routine also automatically calls `MatSetTransposeNullSpace()`. 9007 9008 The user should call `MatNullSpaceDestroy()`. 9009 9010 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, 9011 `KSPSetPCSide()` 9012 @*/ 9013 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) 9014 { 9015 PetscFunctionBegin; 9016 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9017 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9018 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9019 PetscCall(MatNullSpaceDestroy(&mat->nullsp)); 9020 mat->nullsp = nullsp; 9021 if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp)); 9022 PetscFunctionReturn(PETSC_SUCCESS); 9023 } 9024 9025 /*@ 9026 MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix. 9027 9028 Logically Collective 9029 9030 Input Parameters: 9031 + mat - the matrix 9032 - nullsp - the null space object 9033 9034 Level: developer 9035 9036 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()` 9037 @*/ 9038 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) 9039 { 9040 PetscFunctionBegin; 9041 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9042 PetscValidType(mat, 1); 9043 PetscAssertPointer(nullsp, 2); 9044 *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp; 9045 PetscFunctionReturn(PETSC_SUCCESS); 9046 } 9047 9048 /*@ 9049 MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix 9050 9051 Logically Collective 9052 9053 Input Parameters: 9054 + mat - the matrix 9055 - nullsp - the null space object 9056 9057 Level: advanced 9058 9059 Notes: 9060 This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning. 9061 9062 See `MatSetNullSpace()` 9063 9064 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()` 9065 @*/ 9066 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) 9067 { 9068 PetscFunctionBegin; 9069 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9070 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9071 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9072 PetscCall(MatNullSpaceDestroy(&mat->transnullsp)); 9073 mat->transnullsp = nullsp; 9074 PetscFunctionReturn(PETSC_SUCCESS); 9075 } 9076 9077 /*@ 9078 MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions 9079 This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix. 9080 9081 Logically Collective 9082 9083 Input Parameters: 9084 + mat - the matrix 9085 - nullsp - the null space object 9086 9087 Level: advanced 9088 9089 Notes: 9090 Overwrites any previous near null space that may have been attached 9091 9092 You can remove the null space by calling this routine with an `nullsp` of `NULL` 9093 9094 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()` 9095 @*/ 9096 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) 9097 { 9098 PetscFunctionBegin; 9099 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9100 PetscValidType(mat, 1); 9101 if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2); 9102 MatCheckPreallocated(mat, 1); 9103 if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp)); 9104 PetscCall(MatNullSpaceDestroy(&mat->nearnullsp)); 9105 mat->nearnullsp = nullsp; 9106 PetscFunctionReturn(PETSC_SUCCESS); 9107 } 9108 9109 /*@ 9110 MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()` 9111 9112 Not Collective 9113 9114 Input Parameter: 9115 . mat - the matrix 9116 9117 Output Parameter: 9118 . nullsp - the null space object, `NULL` if not set 9119 9120 Level: advanced 9121 9122 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()` 9123 @*/ 9124 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) 9125 { 9126 PetscFunctionBegin; 9127 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9128 PetscValidType(mat, 1); 9129 PetscAssertPointer(nullsp, 2); 9130 MatCheckPreallocated(mat, 1); 9131 *nullsp = mat->nearnullsp; 9132 PetscFunctionReturn(PETSC_SUCCESS); 9133 } 9134 9135 /*@ 9136 MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix. 9137 9138 Collective 9139 9140 Input Parameters: 9141 + mat - the matrix 9142 . row - row/column permutation 9143 - info - information on desired factorization process 9144 9145 Level: developer 9146 9147 Notes: 9148 Probably really in-place only when level of fill is zero, otherwise allocates 9149 new space to store factored matrix and deletes previous memory. 9150 9151 Most users should employ the `KSP` interface for linear solvers 9152 instead of working directly with matrix algebra routines such as this. 9153 See, e.g., `KSPCreate()`. 9154 9155 Fortran Note: 9156 A valid (non-null) `info` argument must be provided 9157 9158 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()` 9159 @*/ 9160 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) 9161 { 9162 PetscFunctionBegin; 9163 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9164 PetscValidType(mat, 1); 9165 if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2); 9166 PetscAssertPointer(info, 3); 9167 PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square"); 9168 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 9169 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 9170 MatCheckPreallocated(mat, 1); 9171 PetscUseTypeMethod(mat, iccfactor, row, info); 9172 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9173 PetscFunctionReturn(PETSC_SUCCESS); 9174 } 9175 9176 /*@ 9177 MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the 9178 ghosted ones. 9179 9180 Not Collective 9181 9182 Input Parameters: 9183 + mat - the matrix 9184 - diag - the diagonal values, including ghost ones 9185 9186 Level: developer 9187 9188 Notes: 9189 Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices 9190 9191 This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()` 9192 9193 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()` 9194 @*/ 9195 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) 9196 { 9197 PetscMPIInt size; 9198 9199 PetscFunctionBegin; 9200 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9201 PetscValidHeaderSpecific(diag, VEC_CLASSID, 2); 9202 PetscValidType(mat, 1); 9203 9204 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled"); 9205 PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0)); 9206 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 9207 if (size == 1) { 9208 PetscInt n, m; 9209 PetscCall(VecGetSize(diag, &n)); 9210 PetscCall(MatGetSize(mat, NULL, &m)); 9211 PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions"); 9212 PetscCall(MatDiagonalScale(mat, NULL, diag)); 9213 } else { 9214 PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag)); 9215 } 9216 PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0)); 9217 PetscCall(PetscObjectStateIncrease((PetscObject)mat)); 9218 PetscFunctionReturn(PETSC_SUCCESS); 9219 } 9220 9221 /*@ 9222 MatGetInertia - Gets the inertia from a factored matrix 9223 9224 Collective 9225 9226 Input Parameter: 9227 . mat - the matrix 9228 9229 Output Parameters: 9230 + nneg - number of negative eigenvalues 9231 . nzero - number of zero eigenvalues 9232 - npos - number of positive eigenvalues 9233 9234 Level: advanced 9235 9236 Note: 9237 Matrix must have been factored by `MatCholeskyFactor()` 9238 9239 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()` 9240 @*/ 9241 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) 9242 { 9243 PetscFunctionBegin; 9244 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9245 PetscValidType(mat, 1); 9246 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9247 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled"); 9248 PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos); 9249 PetscFunctionReturn(PETSC_SUCCESS); 9250 } 9251 9252 /*@C 9253 MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors 9254 9255 Neighbor-wise Collective 9256 9257 Input Parameters: 9258 + mat - the factored matrix obtained with `MatGetFactor()` 9259 - b - the right-hand-side vectors 9260 9261 Output Parameter: 9262 . x - the result vectors 9263 9264 Level: developer 9265 9266 Note: 9267 The vectors `b` and `x` cannot be the same. I.e., one cannot 9268 call `MatSolves`(A,x,x). 9269 9270 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()` 9271 @*/ 9272 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) 9273 { 9274 PetscFunctionBegin; 9275 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9276 PetscValidType(mat, 1); 9277 PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors"); 9278 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix"); 9279 if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS); 9280 9281 MatCheckPreallocated(mat, 1); 9282 PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0)); 9283 PetscUseTypeMethod(mat, solves, b, x); 9284 PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0)); 9285 PetscFunctionReturn(PETSC_SUCCESS); 9286 } 9287 9288 /*@ 9289 MatIsSymmetric - Test whether a matrix is symmetric 9290 9291 Collective 9292 9293 Input Parameters: 9294 + A - the matrix to test 9295 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose) 9296 9297 Output Parameter: 9298 . flg - the result 9299 9300 Level: intermediate 9301 9302 Notes: 9303 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9304 9305 If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()` 9306 9307 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9308 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9309 9310 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`, 9311 `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL` 9312 @*/ 9313 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) 9314 { 9315 PetscFunctionBegin; 9316 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9317 PetscAssertPointer(flg, 3); 9318 if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric); 9319 else { 9320 if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg); 9321 else PetscCall(MatIsTranspose(A, A, tol, flg)); 9322 if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg)); 9323 } 9324 PetscFunctionReturn(PETSC_SUCCESS); 9325 } 9326 9327 /*@ 9328 MatIsHermitian - Test whether a matrix is Hermitian 9329 9330 Collective 9331 9332 Input Parameters: 9333 + A - the matrix to test 9334 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian) 9335 9336 Output Parameter: 9337 . flg - the result 9338 9339 Level: intermediate 9340 9341 Notes: 9342 For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results 9343 9344 If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()` 9345 9346 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9347 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`) 9348 9349 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, 9350 `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL` 9351 @*/ 9352 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) 9353 { 9354 PetscFunctionBegin; 9355 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9356 PetscAssertPointer(flg, 3); 9357 if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian); 9358 else { 9359 if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg); 9360 else PetscCall(MatIsHermitianTranspose(A, A, tol, flg)); 9361 if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg)); 9362 } 9363 PetscFunctionReturn(PETSC_SUCCESS); 9364 } 9365 9366 /*@ 9367 MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state 9368 9369 Not Collective 9370 9371 Input Parameter: 9372 . A - the matrix to check 9373 9374 Output Parameters: 9375 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid) 9376 - flg - the result (only valid if set is `PETSC_TRUE`) 9377 9378 Level: advanced 9379 9380 Notes: 9381 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()` 9382 if you want it explicitly checked 9383 9384 One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric 9385 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9386 9387 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9388 @*/ 9389 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9390 { 9391 PetscFunctionBegin; 9392 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9393 PetscAssertPointer(set, 2); 9394 PetscAssertPointer(flg, 3); 9395 if (A->symmetric != PETSC_BOOL3_UNKNOWN) { 9396 *set = PETSC_TRUE; 9397 *flg = PetscBool3ToBool(A->symmetric); 9398 } else { 9399 *set = PETSC_FALSE; 9400 } 9401 PetscFunctionReturn(PETSC_SUCCESS); 9402 } 9403 9404 /*@ 9405 MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state 9406 9407 Not Collective 9408 9409 Input Parameter: 9410 . A - the matrix to check 9411 9412 Output Parameters: 9413 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid) 9414 - flg - the result (only valid if set is `PETSC_TRUE`) 9415 9416 Level: advanced 9417 9418 Notes: 9419 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). 9420 9421 One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD 9422 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`) 9423 9424 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9425 @*/ 9426 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) 9427 { 9428 PetscFunctionBegin; 9429 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9430 PetscAssertPointer(set, 2); 9431 PetscAssertPointer(flg, 3); 9432 if (A->spd != PETSC_BOOL3_UNKNOWN) { 9433 *set = PETSC_TRUE; 9434 *flg = PetscBool3ToBool(A->spd); 9435 } else { 9436 *set = PETSC_FALSE; 9437 } 9438 PetscFunctionReturn(PETSC_SUCCESS); 9439 } 9440 9441 /*@ 9442 MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state 9443 9444 Not Collective 9445 9446 Input Parameter: 9447 . A - the matrix to check 9448 9449 Output Parameters: 9450 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid) 9451 - flg - the result (only valid if set is `PETSC_TRUE`) 9452 9453 Level: advanced 9454 9455 Notes: 9456 Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()` 9457 if you want it explicitly checked 9458 9459 One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian 9460 after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9461 9462 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()` 9463 @*/ 9464 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) 9465 { 9466 PetscFunctionBegin; 9467 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9468 PetscAssertPointer(set, 2); 9469 PetscAssertPointer(flg, 3); 9470 if (A->hermitian != PETSC_BOOL3_UNKNOWN) { 9471 *set = PETSC_TRUE; 9472 *flg = PetscBool3ToBool(A->hermitian); 9473 } else { 9474 *set = PETSC_FALSE; 9475 } 9476 PetscFunctionReturn(PETSC_SUCCESS); 9477 } 9478 9479 /*@ 9480 MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric 9481 9482 Collective 9483 9484 Input Parameter: 9485 . A - the matrix to test 9486 9487 Output Parameter: 9488 . flg - the result 9489 9490 Level: intermediate 9491 9492 Notes: 9493 If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()` 9494 9495 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 9496 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9497 9498 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()` 9499 @*/ 9500 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) 9501 { 9502 PetscFunctionBegin; 9503 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9504 PetscAssertPointer(flg, 2); 9505 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9506 *flg = PetscBool3ToBool(A->structurally_symmetric); 9507 } else { 9508 PetscUseTypeMethod(A, isstructurallysymmetric, flg); 9509 PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg)); 9510 } 9511 PetscFunctionReturn(PETSC_SUCCESS); 9512 } 9513 9514 /*@ 9515 MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state 9516 9517 Not Collective 9518 9519 Input Parameter: 9520 . A - the matrix to check 9521 9522 Output Parameters: 9523 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid) 9524 - flg - the result (only valid if set is PETSC_TRUE) 9525 9526 Level: advanced 9527 9528 Notes: 9529 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 9530 symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`) 9531 9532 Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation) 9533 9534 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()` 9535 @*/ 9536 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) 9537 { 9538 PetscFunctionBegin; 9539 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 9540 PetscAssertPointer(set, 2); 9541 PetscAssertPointer(flg, 3); 9542 if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) { 9543 *set = PETSC_TRUE; 9544 *flg = PetscBool3ToBool(A->structurally_symmetric); 9545 } else { 9546 *set = PETSC_FALSE; 9547 } 9548 PetscFunctionReturn(PETSC_SUCCESS); 9549 } 9550 9551 /*@ 9552 MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need 9553 to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process 9554 9555 Not Collective 9556 9557 Input Parameter: 9558 . mat - the matrix 9559 9560 Output Parameters: 9561 + nstash - the size of the stash 9562 . reallocs - the number of additional mallocs incurred. 9563 . bnstash - the size of the block stash 9564 - breallocs - the number of additional mallocs incurred.in the block stash 9565 9566 Level: advanced 9567 9568 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()` 9569 @*/ 9570 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) 9571 { 9572 PetscFunctionBegin; 9573 PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs)); 9574 PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs)); 9575 PetscFunctionReturn(PETSC_SUCCESS); 9576 } 9577 9578 /*@ 9579 MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same 9580 parallel layout, `PetscLayout` for rows and columns 9581 9582 Collective 9583 9584 Input Parameter: 9585 . mat - the matrix 9586 9587 Output Parameters: 9588 + right - (optional) vector that the matrix can be multiplied against 9589 - left - (optional) vector that the matrix vector product can be stored in 9590 9591 Level: advanced 9592 9593 Notes: 9594 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()`. 9595 9596 These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed 9597 9598 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()` 9599 @*/ 9600 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) 9601 { 9602 PetscFunctionBegin; 9603 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9604 PetscValidType(mat, 1); 9605 if (mat->ops->getvecs) { 9606 PetscUseTypeMethod(mat, getvecs, right, left); 9607 } else { 9608 if (right) { 9609 PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup"); 9610 PetscCall(VecCreateWithLayout_Private(mat->cmap, right)); 9611 PetscCall(VecSetType(*right, mat->defaultvectype)); 9612 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9613 if (mat->boundtocpu && mat->bindingpropagates) { 9614 PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE)); 9615 PetscCall(VecBindToCPU(*right, PETSC_TRUE)); 9616 } 9617 #endif 9618 } 9619 if (left) { 9620 PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup"); 9621 PetscCall(VecCreateWithLayout_Private(mat->rmap, left)); 9622 PetscCall(VecSetType(*left, mat->defaultvectype)); 9623 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 9624 if (mat->boundtocpu && mat->bindingpropagates) { 9625 PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE)); 9626 PetscCall(VecBindToCPU(*left, PETSC_TRUE)); 9627 } 9628 #endif 9629 } 9630 } 9631 PetscFunctionReturn(PETSC_SUCCESS); 9632 } 9633 9634 /*@ 9635 MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure 9636 with default values. 9637 9638 Not Collective 9639 9640 Input Parameter: 9641 . info - the `MatFactorInfo` data structure 9642 9643 Level: developer 9644 9645 Notes: 9646 The solvers are generally used through the `KSP` and `PC` objects, for example 9647 `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC` 9648 9649 Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed 9650 9651 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo` 9652 @*/ 9653 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) 9654 { 9655 PetscFunctionBegin; 9656 PetscCall(PetscMemzero(info, sizeof(MatFactorInfo))); 9657 PetscFunctionReturn(PETSC_SUCCESS); 9658 } 9659 9660 /*@ 9661 MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed 9662 9663 Collective 9664 9665 Input Parameters: 9666 + mat - the factored matrix 9667 - is - the index set defining the Schur indices (0-based) 9668 9669 Level: advanced 9670 9671 Notes: 9672 Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system. 9673 9674 You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call. 9675 9676 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9677 9678 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`, 9679 `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9680 @*/ 9681 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) 9682 { 9683 PetscErrorCode (*f)(Mat, IS); 9684 9685 PetscFunctionBegin; 9686 PetscValidType(mat, 1); 9687 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 9688 PetscValidType(is, 2); 9689 PetscValidHeaderSpecific(is, IS_CLASSID, 2); 9690 PetscCheckSameComm(mat, 1, is, 2); 9691 PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix"); 9692 PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f)); 9693 PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO"); 9694 PetscCall(MatDestroy(&mat->schur)); 9695 PetscCall((*f)(mat, is)); 9696 PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created"); 9697 PetscFunctionReturn(PETSC_SUCCESS); 9698 } 9699 9700 /*@ 9701 MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step 9702 9703 Logically Collective 9704 9705 Input Parameters: 9706 + F - the factored matrix obtained by calling `MatGetFactor()` 9707 . S - location where to return the Schur complement, can be `NULL` 9708 - status - the status of the Schur complement matrix, can be `NULL` 9709 9710 Level: advanced 9711 9712 Notes: 9713 You must call `MatFactorSetSchurIS()` before calling this routine. 9714 9715 This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO` 9716 9717 The routine provides a copy of the Schur matrix stored within the solver data structures. 9718 The caller must destroy the object when it is no longer needed. 9719 If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse. 9720 9721 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) 9722 9723 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9724 9725 Developer Note: 9726 The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc 9727 matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix. 9728 9729 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO` 9730 @*/ 9731 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9732 { 9733 PetscFunctionBegin; 9734 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9735 if (S) PetscAssertPointer(S, 2); 9736 if (status) PetscAssertPointer(status, 3); 9737 if (S) { 9738 PetscErrorCode (*f)(Mat, Mat *); 9739 9740 PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f)); 9741 if (f) { 9742 PetscCall((*f)(F, S)); 9743 } else { 9744 PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S)); 9745 } 9746 } 9747 if (status) *status = F->schur_status; 9748 PetscFunctionReturn(PETSC_SUCCESS); 9749 } 9750 9751 /*@ 9752 MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix 9753 9754 Logically Collective 9755 9756 Input Parameters: 9757 + F - the factored matrix obtained by calling `MatGetFactor()` 9758 . S - location where to return the Schur complement, can be `NULL` 9759 - status - the status of the Schur complement matrix, can be `NULL` 9760 9761 Level: advanced 9762 9763 Notes: 9764 You must call `MatFactorSetSchurIS()` before calling this routine. 9765 9766 Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS` 9767 9768 The routine returns a the Schur Complement stored within the data structures of the solver. 9769 9770 If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement. 9771 9772 The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed. 9773 9774 Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix 9775 9776 See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements. 9777 9778 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9779 @*/ 9780 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) 9781 { 9782 PetscFunctionBegin; 9783 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9784 if (S) { 9785 PetscAssertPointer(S, 2); 9786 *S = F->schur; 9787 } 9788 if (status) { 9789 PetscAssertPointer(status, 3); 9790 *status = F->schur_status; 9791 } 9792 PetscFunctionReturn(PETSC_SUCCESS); 9793 } 9794 9795 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F) 9796 { 9797 Mat S = F->schur; 9798 9799 PetscFunctionBegin; 9800 switch (F->schur_status) { 9801 case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through 9802 case MAT_FACTOR_SCHUR_INVERTED: 9803 if (S) { 9804 S->ops->solve = NULL; 9805 S->ops->matsolve = NULL; 9806 S->ops->solvetranspose = NULL; 9807 S->ops->matsolvetranspose = NULL; 9808 S->ops->solveadd = NULL; 9809 S->ops->solvetransposeadd = NULL; 9810 S->factortype = MAT_FACTOR_NONE; 9811 PetscCall(PetscFree(S->solvertype)); 9812 } 9813 case MAT_FACTOR_SCHUR_FACTORED: // fall-through 9814 break; 9815 default: 9816 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9817 } 9818 PetscFunctionReturn(PETSC_SUCCESS); 9819 } 9820 9821 /*@ 9822 MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()` 9823 9824 Logically Collective 9825 9826 Input Parameters: 9827 + F - the factored matrix obtained by calling `MatGetFactor()` 9828 . S - location where the Schur complement is stored 9829 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`) 9830 9831 Level: advanced 9832 9833 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus` 9834 @*/ 9835 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) 9836 { 9837 PetscFunctionBegin; 9838 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9839 if (S) { 9840 PetscValidHeaderSpecific(*S, MAT_CLASSID, 2); 9841 *S = NULL; 9842 } 9843 F->schur_status = status; 9844 PetscCall(MatFactorUpdateSchurStatus_Private(F)); 9845 PetscFunctionReturn(PETSC_SUCCESS); 9846 } 9847 9848 /*@ 9849 MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step 9850 9851 Logically Collective 9852 9853 Input Parameters: 9854 + F - the factored matrix obtained by calling `MatGetFactor()` 9855 . rhs - location where the right-hand side of the Schur complement system is stored 9856 - sol - location where the solution of the Schur complement system has to be returned 9857 9858 Level: advanced 9859 9860 Notes: 9861 The sizes of the vectors should match the size of the Schur complement 9862 9863 Must be called after `MatFactorSetSchurIS()` 9864 9865 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()` 9866 @*/ 9867 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) 9868 { 9869 PetscFunctionBegin; 9870 PetscValidType(F, 1); 9871 PetscValidType(rhs, 2); 9872 PetscValidType(sol, 3); 9873 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9874 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9875 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9876 PetscCheckSameComm(F, 1, rhs, 2); 9877 PetscCheckSameComm(F, 1, sol, 3); 9878 PetscCall(MatFactorFactorizeSchurComplement(F)); 9879 switch (F->schur_status) { 9880 case MAT_FACTOR_SCHUR_FACTORED: 9881 PetscCall(MatSolveTranspose(F->schur, rhs, sol)); 9882 break; 9883 case MAT_FACTOR_SCHUR_INVERTED: 9884 PetscCall(MatMultTranspose(F->schur, rhs, sol)); 9885 break; 9886 default: 9887 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9888 } 9889 PetscFunctionReturn(PETSC_SUCCESS); 9890 } 9891 9892 /*@ 9893 MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step 9894 9895 Logically Collective 9896 9897 Input Parameters: 9898 + F - the factored matrix obtained by calling `MatGetFactor()` 9899 . rhs - location where the right-hand side of the Schur complement system is stored 9900 - sol - location where the solution of the Schur complement system has to be returned 9901 9902 Level: advanced 9903 9904 Notes: 9905 The sizes of the vectors should match the size of the Schur complement 9906 9907 Must be called after `MatFactorSetSchurIS()` 9908 9909 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()` 9910 @*/ 9911 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) 9912 { 9913 PetscFunctionBegin; 9914 PetscValidType(F, 1); 9915 PetscValidType(rhs, 2); 9916 PetscValidType(sol, 3); 9917 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9918 PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2); 9919 PetscValidHeaderSpecific(sol, VEC_CLASSID, 3); 9920 PetscCheckSameComm(F, 1, rhs, 2); 9921 PetscCheckSameComm(F, 1, sol, 3); 9922 PetscCall(MatFactorFactorizeSchurComplement(F)); 9923 switch (F->schur_status) { 9924 case MAT_FACTOR_SCHUR_FACTORED: 9925 PetscCall(MatSolve(F->schur, rhs, sol)); 9926 break; 9927 case MAT_FACTOR_SCHUR_INVERTED: 9928 PetscCall(MatMult(F->schur, rhs, sol)); 9929 break; 9930 default: 9931 SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status); 9932 } 9933 PetscFunctionReturn(PETSC_SUCCESS); 9934 } 9935 9936 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat); 9937 #if PetscDefined(HAVE_CUDA) 9938 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat); 9939 #endif 9940 9941 /* Schur status updated in the interface */ 9942 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F) 9943 { 9944 Mat S = F->schur; 9945 9946 PetscFunctionBegin; 9947 if (S) { 9948 PetscMPIInt size; 9949 PetscBool isdense, isdensecuda; 9950 9951 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size)); 9952 PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented"); 9953 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense)); 9954 PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda)); 9955 PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name); 9956 PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0)); 9957 if (isdense) { 9958 PetscCall(MatSeqDenseInvertFactors_Private(S)); 9959 } else if (isdensecuda) { 9960 #if defined(PETSC_HAVE_CUDA) 9961 PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S)); 9962 #endif 9963 } 9964 // HIP?????????????? 9965 PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0)); 9966 } 9967 PetscFunctionReturn(PETSC_SUCCESS); 9968 } 9969 9970 /*@ 9971 MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step 9972 9973 Logically Collective 9974 9975 Input Parameter: 9976 . F - the factored matrix obtained by calling `MatGetFactor()` 9977 9978 Level: advanced 9979 9980 Notes: 9981 Must be called after `MatFactorSetSchurIS()`. 9982 9983 Call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it. 9984 9985 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()` 9986 @*/ 9987 PetscErrorCode MatFactorInvertSchurComplement(Mat F) 9988 { 9989 PetscFunctionBegin; 9990 PetscValidType(F, 1); 9991 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 9992 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS); 9993 PetscCall(MatFactorFactorizeSchurComplement(F)); 9994 PetscCall(MatFactorInvertSchurComplement_Private(F)); 9995 F->schur_status = MAT_FACTOR_SCHUR_INVERTED; 9996 PetscFunctionReturn(PETSC_SUCCESS); 9997 } 9998 9999 /*@ 10000 MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step 10001 10002 Logically Collective 10003 10004 Input Parameter: 10005 . F - the factored matrix obtained by calling `MatGetFactor()` 10006 10007 Level: advanced 10008 10009 Note: 10010 Must be called after `MatFactorSetSchurIS()` 10011 10012 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()` 10013 @*/ 10014 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) 10015 { 10016 MatFactorInfo info; 10017 10018 PetscFunctionBegin; 10019 PetscValidType(F, 1); 10020 PetscValidHeaderSpecific(F, MAT_CLASSID, 1); 10021 if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS); 10022 PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0)); 10023 PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo))); 10024 if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */ 10025 PetscCall(MatCholeskyFactor(F->schur, NULL, &info)); 10026 } else { 10027 PetscCall(MatLUFactor(F->schur, NULL, NULL, &info)); 10028 } 10029 PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0)); 10030 F->schur_status = MAT_FACTOR_SCHUR_FACTORED; 10031 PetscFunctionReturn(PETSC_SUCCESS); 10032 } 10033 10034 /*@ 10035 MatPtAP - Creates the matrix product $C = P^T * A * P$ 10036 10037 Neighbor-wise Collective 10038 10039 Input Parameters: 10040 + A - the matrix 10041 . P - the projection matrix 10042 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10043 - 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 10044 if the result is a dense matrix this is irrelevant 10045 10046 Output Parameter: 10047 . C - the product matrix 10048 10049 Level: intermediate 10050 10051 Notes: 10052 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10053 10054 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_PtAP` 10055 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10056 10057 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10058 10059 Developer Note: 10060 For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`. 10061 10062 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()` 10063 @*/ 10064 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) 10065 { 10066 PetscFunctionBegin; 10067 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10068 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10069 10070 if (scall == MAT_INITIAL_MATRIX) { 10071 PetscCall(MatProductCreate(A, P, NULL, C)); 10072 PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP)); 10073 PetscCall(MatProductSetAlgorithm(*C, "default")); 10074 PetscCall(MatProductSetFill(*C, fill)); 10075 10076 (*C)->product->api_user = PETSC_TRUE; 10077 PetscCall(MatProductSetFromOptions(*C)); 10078 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); 10079 PetscCall(MatProductSymbolic(*C)); 10080 } else { /* scall == MAT_REUSE_MATRIX */ 10081 PetscCall(MatProductReplaceMats(A, P, NULL, *C)); 10082 } 10083 10084 PetscCall(MatProductNumeric(*C)); 10085 (*C)->symmetric = A->symmetric; 10086 (*C)->spd = A->spd; 10087 PetscFunctionReturn(PETSC_SUCCESS); 10088 } 10089 10090 /*@ 10091 MatRARt - Creates the matrix product $C = R * A * R^T$ 10092 10093 Neighbor-wise Collective 10094 10095 Input Parameters: 10096 + A - the matrix 10097 . R - the projection matrix 10098 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10099 - fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate 10100 if the result is a dense matrix this is irrelevant 10101 10102 Output Parameter: 10103 . C - the product matrix 10104 10105 Level: intermediate 10106 10107 Notes: 10108 `C` will be created and must be destroyed by the user with `MatDestroy()`. 10109 10110 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_RARt` 10111 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10112 10113 This routine is currently only implemented for pairs of `MATAIJ` matrices and classes 10114 which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes, 10115 the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive. 10116 We recommend using `MatPtAP()` when possible. 10117 10118 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10119 10120 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()` 10121 @*/ 10122 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) 10123 { 10124 PetscFunctionBegin; 10125 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5); 10126 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10127 10128 if (scall == MAT_INITIAL_MATRIX) { 10129 PetscCall(MatProductCreate(A, R, NULL, C)); 10130 PetscCall(MatProductSetType(*C, MATPRODUCT_RARt)); 10131 PetscCall(MatProductSetAlgorithm(*C, "default")); 10132 PetscCall(MatProductSetFill(*C, fill)); 10133 10134 (*C)->product->api_user = PETSC_TRUE; 10135 PetscCall(MatProductSetFromOptions(*C)); 10136 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); 10137 PetscCall(MatProductSymbolic(*C)); 10138 } else { /* scall == MAT_REUSE_MATRIX */ 10139 PetscCall(MatProductReplaceMats(A, R, NULL, *C)); 10140 } 10141 10142 PetscCall(MatProductNumeric(*C)); 10143 if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10144 PetscFunctionReturn(PETSC_SUCCESS); 10145 } 10146 10147 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) 10148 { 10149 PetscBool flg = PETSC_TRUE; 10150 10151 PetscFunctionBegin; 10152 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported"); 10153 if (scall == MAT_INITIAL_MATRIX) { 10154 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype])); 10155 PetscCall(MatProductCreate(A, B, NULL, C)); 10156 PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT)); 10157 PetscCall(MatProductSetFill(*C, fill)); 10158 } else { /* scall == MAT_REUSE_MATRIX */ 10159 Mat_Product *product = (*C)->product; 10160 10161 PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, "")); 10162 if (flg && product && product->type != ptype) { 10163 PetscCall(MatProductClear(*C)); 10164 product = NULL; 10165 } 10166 PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype])); 10167 if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */ 10168 PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first"); 10169 PetscCall(MatProductCreate_Private(A, B, NULL, *C)); 10170 product = (*C)->product; 10171 product->fill = fill; 10172 product->clear = PETSC_TRUE; 10173 } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */ 10174 flg = PETSC_FALSE; 10175 PetscCall(MatProductReplaceMats(A, B, NULL, *C)); 10176 } 10177 } 10178 if (flg) { 10179 (*C)->product->api_user = PETSC_TRUE; 10180 PetscCall(MatProductSetType(*C, ptype)); 10181 PetscCall(MatProductSetFromOptions(*C)); 10182 PetscCall(MatProductSymbolic(*C)); 10183 } 10184 PetscCall(MatProductNumeric(*C)); 10185 PetscFunctionReturn(PETSC_SUCCESS); 10186 } 10187 10188 /*@ 10189 MatMatMult - Performs matrix-matrix multiplication $ C=A*B $. 10190 10191 Neighbor-wise Collective 10192 10193 Input Parameters: 10194 + A - the left matrix 10195 . B - the right matrix 10196 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10197 - 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 10198 if the result is a dense matrix this is irrelevant 10199 10200 Output Parameter: 10201 . C - the product matrix 10202 10203 Notes: 10204 Unless scall is `MAT_REUSE_MATRIX` C will be created. 10205 10206 `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 10207 call to this function with `MAT_INITIAL_MATRIX`. 10208 10209 To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed. 10210 10211 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`, 10212 rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse. 10213 10214 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10215 10216 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_AB` 10217 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10218 10219 Example of Usage: 10220 .vb 10221 MatProductCreate(A,B,NULL,&C); 10222 MatProductSetType(C,MATPRODUCT_AB); 10223 MatProductSymbolic(C); 10224 MatProductNumeric(C); // compute C=A * B 10225 MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1 10226 MatProductNumeric(C); 10227 MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1 10228 MatProductNumeric(C); 10229 .ve 10230 10231 Level: intermediate 10232 10233 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()` 10234 @*/ 10235 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10236 { 10237 PetscFunctionBegin; 10238 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C)); 10239 PetscFunctionReturn(PETSC_SUCCESS); 10240 } 10241 10242 /*@ 10243 MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$. 10244 10245 Neighbor-wise Collective 10246 10247 Input Parameters: 10248 + A - the left matrix 10249 . B - the right matrix 10250 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10251 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10252 10253 Output Parameter: 10254 . C - the product matrix 10255 10256 Options Database Key: 10257 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the 10258 first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity; 10259 the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity. 10260 10261 Level: intermediate 10262 10263 Notes: 10264 C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10265 10266 `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call 10267 10268 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10269 actually needed. 10270 10271 This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class, 10272 and for pairs of `MATMPIDENSE` matrices. 10273 10274 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_ABt` 10275 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10276 10277 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10278 10279 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType` 10280 @*/ 10281 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10282 { 10283 PetscFunctionBegin; 10284 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C)); 10285 if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE)); 10286 PetscFunctionReturn(PETSC_SUCCESS); 10287 } 10288 10289 /*@ 10290 MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$. 10291 10292 Neighbor-wise Collective 10293 10294 Input Parameters: 10295 + A - the left matrix 10296 . B - the right matrix 10297 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10298 - fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known 10299 10300 Output Parameter: 10301 . C - the product matrix 10302 10303 Level: intermediate 10304 10305 Notes: 10306 `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`. 10307 10308 `MAT_REUSE_MATRIX` can only be used if `A` and `B` have the same nonzero pattern as in the previous call. 10309 10310 This is a convenience routine that wraps the use of `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_AtB` 10311 functionality into a single function call. For more involved matrix-matrix operations see `MatProductCreate()`. 10312 10313 To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value 10314 actually needed. 10315 10316 This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes 10317 which inherit from `MATSEQAIJ`. `C` will be of the same type as the input matrices. 10318 10319 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10320 10321 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()` 10322 @*/ 10323 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) 10324 { 10325 PetscFunctionBegin; 10326 PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C)); 10327 PetscFunctionReturn(PETSC_SUCCESS); 10328 } 10329 10330 /*@ 10331 MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C. 10332 10333 Neighbor-wise Collective 10334 10335 Input Parameters: 10336 + A - the left matrix 10337 . B - the middle matrix 10338 . C - the right matrix 10339 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10340 - 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 10341 if the result is a dense matrix this is irrelevant 10342 10343 Output Parameter: 10344 . D - the product matrix 10345 10346 Level: intermediate 10347 10348 Notes: 10349 Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created. 10350 10351 `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call 10352 10353 This is a convenience routine that wraps the use of the `MatProductCreate()` with a `MatProductType` of `MATPRODUCT_ABC` 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 If you have many matrices with the same non-zero structure to multiply, you 10360 should use `MAT_REUSE_MATRIX` in all calls but the first 10361 10362 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 10363 10364 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()` 10365 @*/ 10366 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) 10367 { 10368 PetscFunctionBegin; 10369 if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6); 10370 PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 10371 10372 if (scall == MAT_INITIAL_MATRIX) { 10373 PetscCall(MatProductCreate(A, B, C, D)); 10374 PetscCall(MatProductSetType(*D, MATPRODUCT_ABC)); 10375 PetscCall(MatProductSetAlgorithm(*D, "default")); 10376 PetscCall(MatProductSetFill(*D, fill)); 10377 10378 (*D)->product->api_user = PETSC_TRUE; 10379 PetscCall(MatProductSetFromOptions(*D)); 10380 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, 10381 ((PetscObject)C)->type_name); 10382 PetscCall(MatProductSymbolic(*D)); 10383 } else { /* user may change input matrices when REUSE */ 10384 PetscCall(MatProductReplaceMats(A, B, C, *D)); 10385 } 10386 PetscCall(MatProductNumeric(*D)); 10387 PetscFunctionReturn(PETSC_SUCCESS); 10388 } 10389 10390 /*@ 10391 MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators. 10392 10393 Collective 10394 10395 Input Parameters: 10396 + mat - the matrix 10397 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices) 10398 . subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used) 10399 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10400 10401 Output Parameter: 10402 . matredundant - redundant matrix 10403 10404 Level: advanced 10405 10406 Notes: 10407 `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the 10408 original matrix has not changed from that last call to `MatCreateRedundantMatrix()`. 10409 10410 This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before 10411 calling it. 10412 10413 `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be. 10414 10415 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm` 10416 @*/ 10417 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) 10418 { 10419 MPI_Comm comm; 10420 PetscMPIInt size; 10421 PetscInt mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs; 10422 Mat_Redundant *redund = NULL; 10423 PetscSubcomm psubcomm = NULL; 10424 MPI_Comm subcomm_in = subcomm; 10425 Mat *matseq; 10426 IS isrow, iscol; 10427 PetscBool newsubcomm = PETSC_FALSE; 10428 10429 PetscFunctionBegin; 10430 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10431 if (nsubcomm && reuse == MAT_REUSE_MATRIX) { 10432 PetscAssertPointer(*matredundant, 5); 10433 PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5); 10434 } 10435 10436 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 10437 if (size == 1 || nsubcomm == 1) { 10438 if (reuse == MAT_INITIAL_MATRIX) { 10439 PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant)); 10440 } else { 10441 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"); 10442 PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN)); 10443 } 10444 PetscFunctionReturn(PETSC_SUCCESS); 10445 } 10446 10447 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10448 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10449 MatCheckPreallocated(mat, 1); 10450 10451 PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0)); 10452 if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */ 10453 /* create psubcomm, then get subcomm */ 10454 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10455 PetscCallMPI(MPI_Comm_size(comm, &size)); 10456 PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size); 10457 10458 PetscCall(PetscSubcommCreate(comm, &psubcomm)); 10459 PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm)); 10460 PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS)); 10461 PetscCall(PetscSubcommSetFromOptions(psubcomm)); 10462 PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL)); 10463 newsubcomm = PETSC_TRUE; 10464 PetscCall(PetscSubcommDestroy(&psubcomm)); 10465 } 10466 10467 /* get isrow, iscol and a local sequential matrix matseq[0] */ 10468 if (reuse == MAT_INITIAL_MATRIX) { 10469 mloc_sub = PETSC_DECIDE; 10470 nloc_sub = PETSC_DECIDE; 10471 if (bs < 1) { 10472 PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M)); 10473 PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N)); 10474 } else { 10475 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M)); 10476 PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N)); 10477 } 10478 PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm)); 10479 rstart = rend - mloc_sub; 10480 PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow)); 10481 PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol)); 10482 PetscCall(ISSetIdentity(iscol)); 10483 } else { /* reuse == MAT_REUSE_MATRIX */ 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 /* retrieve subcomm */ 10486 PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm)); 10487 redund = (*matredundant)->redundant; 10488 isrow = redund->isrow; 10489 iscol = redund->iscol; 10490 matseq = redund->matseq; 10491 } 10492 PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq)); 10493 10494 /* get matredundant over subcomm */ 10495 if (reuse == MAT_INITIAL_MATRIX) { 10496 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant)); 10497 10498 /* create a supporting struct and attach it to C for reuse */ 10499 PetscCall(PetscNew(&redund)); 10500 (*matredundant)->redundant = redund; 10501 redund->isrow = isrow; 10502 redund->iscol = iscol; 10503 redund->matseq = matseq; 10504 if (newsubcomm) { 10505 redund->subcomm = subcomm; 10506 } else { 10507 redund->subcomm = MPI_COMM_NULL; 10508 } 10509 } else { 10510 PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant)); 10511 } 10512 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP) 10513 if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) { 10514 PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE)); 10515 PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE)); 10516 } 10517 #endif 10518 PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0)); 10519 PetscFunctionReturn(PETSC_SUCCESS); 10520 } 10521 10522 /*@C 10523 MatGetMultiProcBlock - Create multiple 'parallel submatrices' from 10524 a given `Mat`. Each submatrix can span multiple procs. 10525 10526 Collective 10527 10528 Input Parameters: 10529 + mat - the matrix 10530 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))` 10531 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 10532 10533 Output Parameter: 10534 . subMat - parallel sub-matrices each spanning a given `subcomm` 10535 10536 Level: advanced 10537 10538 Notes: 10539 The submatrix partition across processors is dictated by `subComm` a 10540 communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm` 10541 is not restricted to be grouped with consecutive original MPI processes. 10542 10543 Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices 10544 map directly to the layout of the original matrix [wrt the local 10545 row,col partitioning]. So the original 'DiagonalMat' naturally maps 10546 into the 'DiagonalMat' of the `subMat`, hence it is used directly from 10547 the `subMat`. However the offDiagMat looses some columns - and this is 10548 reconstructed with `MatSetValues()` 10549 10550 This is used by `PCBJACOBI` when a single block spans multiple MPI processes. 10551 10552 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI` 10553 @*/ 10554 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) 10555 { 10556 PetscMPIInt commsize, subCommSize; 10557 10558 PetscFunctionBegin; 10559 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize)); 10560 PetscCallMPI(MPI_Comm_size(subComm, &subCommSize)); 10561 PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize); 10562 10563 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"); 10564 PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10565 PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat); 10566 PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0)); 10567 PetscFunctionReturn(PETSC_SUCCESS); 10568 } 10569 10570 /*@ 10571 MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering 10572 10573 Not Collective 10574 10575 Input Parameters: 10576 + mat - matrix to extract local submatrix from 10577 . isrow - local row indices for submatrix 10578 - iscol - local column indices for submatrix 10579 10580 Output Parameter: 10581 . submat - the submatrix 10582 10583 Level: intermediate 10584 10585 Notes: 10586 `submat` should be disposed of with `MatRestoreLocalSubMatrix()`. 10587 10588 Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`. Its communicator may be 10589 the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s. 10590 10591 `submat` always implements `MatSetValuesLocal()`. If `isrow` and `iscol` have the same block size, then 10592 `MatSetValuesBlockedLocal()` will also be implemented. 10593 10594 `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`. 10595 Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided. 10596 10597 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()` 10598 @*/ 10599 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10600 { 10601 PetscFunctionBegin; 10602 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10603 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10604 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10605 PetscCheckSameComm(isrow, 2, iscol, 3); 10606 PetscAssertPointer(submat, 4); 10607 PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call"); 10608 10609 if (mat->ops->getlocalsubmatrix) { 10610 PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat); 10611 } else { 10612 PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat)); 10613 } 10614 (*submat)->assembled = mat->assembled; 10615 PetscFunctionReturn(PETSC_SUCCESS); 10616 } 10617 10618 /*@ 10619 MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()` 10620 10621 Not Collective 10622 10623 Input Parameters: 10624 + mat - matrix to extract local submatrix from 10625 . isrow - local row indices for submatrix 10626 . iscol - local column indices for submatrix 10627 - submat - the submatrix 10628 10629 Level: intermediate 10630 10631 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()` 10632 @*/ 10633 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) 10634 { 10635 PetscFunctionBegin; 10636 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10637 PetscValidHeaderSpecific(isrow, IS_CLASSID, 2); 10638 PetscValidHeaderSpecific(iscol, IS_CLASSID, 3); 10639 PetscCheckSameComm(isrow, 2, iscol, 3); 10640 PetscAssertPointer(submat, 4); 10641 if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); 10642 10643 if (mat->ops->restorelocalsubmatrix) { 10644 PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat); 10645 } else { 10646 PetscCall(MatDestroy(submat)); 10647 } 10648 *submat = NULL; 10649 PetscFunctionReturn(PETSC_SUCCESS); 10650 } 10651 10652 /*@ 10653 MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix 10654 10655 Collective 10656 10657 Input Parameter: 10658 . mat - the matrix 10659 10660 Output Parameter: 10661 . is - if any rows have zero diagonals this contains the list of them 10662 10663 Level: developer 10664 10665 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10666 @*/ 10667 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) 10668 { 10669 PetscFunctionBegin; 10670 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10671 PetscValidType(mat, 1); 10672 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10673 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10674 10675 if (!mat->ops->findzerodiagonals) { 10676 Vec diag; 10677 const PetscScalar *a; 10678 PetscInt *rows; 10679 PetscInt rStart, rEnd, r, nrow = 0; 10680 10681 PetscCall(MatCreateVecs(mat, &diag, NULL)); 10682 PetscCall(MatGetDiagonal(mat, diag)); 10683 PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd)); 10684 PetscCall(VecGetArrayRead(diag, &a)); 10685 for (r = 0; r < rEnd - rStart; ++r) 10686 if (a[r] == 0.0) ++nrow; 10687 PetscCall(PetscMalloc1(nrow, &rows)); 10688 nrow = 0; 10689 for (r = 0; r < rEnd - rStart; ++r) 10690 if (a[r] == 0.0) rows[nrow++] = r + rStart; 10691 PetscCall(VecRestoreArrayRead(diag, &a)); 10692 PetscCall(VecDestroy(&diag)); 10693 PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is)); 10694 } else { 10695 PetscUseTypeMethod(mat, findzerodiagonals, is); 10696 } 10697 PetscFunctionReturn(PETSC_SUCCESS); 10698 } 10699 10700 /*@ 10701 MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size) 10702 10703 Collective 10704 10705 Input Parameter: 10706 . mat - the matrix 10707 10708 Output Parameter: 10709 . is - contains the list of rows with off block diagonal entries 10710 10711 Level: developer 10712 10713 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()` 10714 @*/ 10715 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) 10716 { 10717 PetscFunctionBegin; 10718 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10719 PetscValidType(mat, 1); 10720 PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10721 PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10722 10723 PetscUseTypeMethod(mat, findoffblockdiagonalentries, is); 10724 PetscFunctionReturn(PETSC_SUCCESS); 10725 } 10726 10727 /*@C 10728 MatInvertBlockDiagonal - Inverts the block diagonal entries. 10729 10730 Collective; No Fortran Support 10731 10732 Input Parameter: 10733 . mat - the matrix 10734 10735 Output Parameter: 10736 . values - the block inverses in column major order (FORTRAN-like) 10737 10738 Level: advanced 10739 10740 Notes: 10741 The size of the blocks is determined by the block size of the matrix. 10742 10743 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10744 10745 The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size 10746 10747 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()` 10748 @*/ 10749 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[]) 10750 { 10751 PetscFunctionBegin; 10752 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10753 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10754 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10755 PetscUseTypeMethod(mat, invertblockdiagonal, values); 10756 PetscFunctionReturn(PETSC_SUCCESS); 10757 } 10758 10759 /*@ 10760 MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries. 10761 10762 Collective; No Fortran Support 10763 10764 Input Parameters: 10765 + mat - the matrix 10766 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()` 10767 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()` 10768 10769 Output Parameter: 10770 . values - the block inverses in column major order (FORTRAN-like) 10771 10772 Level: advanced 10773 10774 Notes: 10775 Use `MatInvertBlockDiagonal()` if all blocks have the same size 10776 10777 The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case 10778 10779 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()` 10780 @*/ 10781 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[]) 10782 { 10783 PetscFunctionBegin; 10784 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10785 PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 10786 PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 10787 PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values); 10788 PetscFunctionReturn(PETSC_SUCCESS); 10789 } 10790 10791 /*@ 10792 MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A 10793 10794 Collective 10795 10796 Input Parameters: 10797 + A - the matrix 10798 - C - matrix with inverted block diagonal of `A`. This matrix should be created and may have its type set. 10799 10800 Level: advanced 10801 10802 Note: 10803 The blocksize of the matrix is used to determine the blocks on the diagonal of `C` 10804 10805 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()` 10806 @*/ 10807 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) 10808 { 10809 const PetscScalar *vals; 10810 PetscInt *dnnz; 10811 PetscInt m, rstart, rend, bs, i, j; 10812 10813 PetscFunctionBegin; 10814 PetscCall(MatInvertBlockDiagonal(A, &vals)); 10815 PetscCall(MatGetBlockSize(A, &bs)); 10816 PetscCall(MatGetLocalSize(A, &m, NULL)); 10817 PetscCall(MatSetLayouts(C, A->rmap, A->cmap)); 10818 PetscCall(MatSetBlockSizes(C, A->rmap->bs, A->cmap->bs)); 10819 PetscCall(PetscMalloc1(m / bs, &dnnz)); 10820 for (j = 0; j < m / bs; j++) dnnz[j] = 1; 10821 PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL)); 10822 PetscCall(PetscFree(dnnz)); 10823 PetscCall(MatGetOwnershipRange(C, &rstart, &rend)); 10824 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE)); 10825 for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES)); 10826 PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); 10827 PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); 10828 PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE)); 10829 PetscFunctionReturn(PETSC_SUCCESS); 10830 } 10831 10832 /*@ 10833 MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created 10834 via `MatTransposeColoringCreate()`. 10835 10836 Collective 10837 10838 Input Parameter: 10839 . c - coloring context 10840 10841 Level: intermediate 10842 10843 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()` 10844 @*/ 10845 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) 10846 { 10847 MatTransposeColoring matcolor = *c; 10848 10849 PetscFunctionBegin; 10850 if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS); 10851 if (--((PetscObject)matcolor)->refct > 0) { 10852 matcolor = NULL; 10853 PetscFunctionReturn(PETSC_SUCCESS); 10854 } 10855 10856 PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow)); 10857 PetscCall(PetscFree(matcolor->rows)); 10858 PetscCall(PetscFree(matcolor->den2sp)); 10859 PetscCall(PetscFree(matcolor->colorforcol)); 10860 PetscCall(PetscFree(matcolor->columns)); 10861 if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart)); 10862 PetscCall(PetscHeaderDestroy(c)); 10863 PetscFunctionReturn(PETSC_SUCCESS); 10864 } 10865 10866 /*@ 10867 MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which 10868 a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying 10869 `MatTransposeColoring` to sparse `B`. 10870 10871 Collective 10872 10873 Input Parameters: 10874 + coloring - coloring context created with `MatTransposeColoringCreate()` 10875 - B - sparse matrix 10876 10877 Output Parameter: 10878 . Btdense - dense matrix $B^T$ 10879 10880 Level: developer 10881 10882 Note: 10883 These are used internally for some implementations of `MatRARt()` 10884 10885 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()` 10886 @*/ 10887 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) 10888 { 10889 PetscFunctionBegin; 10890 PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10891 PetscValidHeaderSpecific(B, MAT_CLASSID, 2); 10892 PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3); 10893 10894 PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense)); 10895 PetscFunctionReturn(PETSC_SUCCESS); 10896 } 10897 10898 /*@ 10899 MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which 10900 a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$ 10901 in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix 10902 $C_{sp}$ from $C_{den}$. 10903 10904 Collective 10905 10906 Input Parameters: 10907 + matcoloring - coloring context created with `MatTransposeColoringCreate()` 10908 - Cden - matrix product of a sparse matrix and a dense matrix Btdense 10909 10910 Output Parameter: 10911 . Csp - sparse matrix 10912 10913 Level: developer 10914 10915 Note: 10916 These are used internally for some implementations of `MatRARt()` 10917 10918 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()` 10919 @*/ 10920 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) 10921 { 10922 PetscFunctionBegin; 10923 PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1); 10924 PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2); 10925 PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3); 10926 10927 PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp)); 10928 PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY)); 10929 PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY)); 10930 PetscFunctionReturn(PETSC_SUCCESS); 10931 } 10932 10933 /*@ 10934 MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$. 10935 10936 Collective 10937 10938 Input Parameters: 10939 + mat - the matrix product C 10940 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()` 10941 10942 Output Parameter: 10943 . color - the new coloring context 10944 10945 Level: intermediate 10946 10947 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`, 10948 `MatTransColoringApplyDenToSp()` 10949 @*/ 10950 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) 10951 { 10952 MatTransposeColoring c; 10953 MPI_Comm comm; 10954 10955 PetscFunctionBegin; 10956 PetscAssertPointer(color, 3); 10957 10958 PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10959 PetscCall(PetscObjectGetComm((PetscObject)mat, &comm)); 10960 PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL)); 10961 c->ctype = iscoloring->ctype; 10962 PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c); 10963 *color = c; 10964 PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0)); 10965 PetscFunctionReturn(PETSC_SUCCESS); 10966 } 10967 10968 /*@ 10969 MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the 10970 matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger. 10971 10972 Not Collective 10973 10974 Input Parameter: 10975 . mat - the matrix 10976 10977 Output Parameter: 10978 . state - the current state 10979 10980 Level: intermediate 10981 10982 Notes: 10983 You can only compare states from two different calls to the SAME matrix, you cannot compare calls between 10984 different matrices 10985 10986 Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix 10987 10988 Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers. 10989 10990 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()` 10991 @*/ 10992 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) 10993 { 10994 PetscFunctionBegin; 10995 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 10996 *state = mat->nonzerostate; 10997 PetscFunctionReturn(PETSC_SUCCESS); 10998 } 10999 11000 /*@ 11001 MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential 11002 matrices from each processor 11003 11004 Collective 11005 11006 Input Parameters: 11007 + comm - the communicators the parallel matrix will live on 11008 . seqmat - the input sequential matrices 11009 . n - number of local columns (or `PETSC_DECIDE`) 11010 - reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11011 11012 Output Parameter: 11013 . mpimat - the parallel matrix generated 11014 11015 Level: developer 11016 11017 Note: 11018 The number of columns of the matrix in EACH processor MUST be the same. 11019 11020 .seealso: [](ch_matrices), `Mat` 11021 @*/ 11022 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) 11023 { 11024 PetscMPIInt size; 11025 11026 PetscFunctionBegin; 11027 PetscCallMPI(MPI_Comm_size(comm, &size)); 11028 if (size == 1) { 11029 if (reuse == MAT_INITIAL_MATRIX) { 11030 PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat)); 11031 } else { 11032 PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN)); 11033 } 11034 PetscFunctionReturn(PETSC_SUCCESS); 11035 } 11036 11037 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"); 11038 11039 PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0)); 11040 PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat)); 11041 PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0)); 11042 PetscFunctionReturn(PETSC_SUCCESS); 11043 } 11044 11045 /*@ 11046 MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges. 11047 11048 Collective 11049 11050 Input Parameters: 11051 + A - the matrix to create subdomains from 11052 - N - requested number of subdomains 11053 11054 Output Parameters: 11055 + n - number of subdomains resulting on this MPI process 11056 - iss - `IS` list with indices of subdomains on this MPI process 11057 11058 Level: advanced 11059 11060 Note: 11061 The number of subdomains must be smaller than the communicator size 11062 11063 .seealso: [](ch_matrices), `Mat`, `IS` 11064 @*/ 11065 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) 11066 { 11067 MPI_Comm comm, subcomm; 11068 PetscMPIInt size, rank, color; 11069 PetscInt rstart, rend, k; 11070 11071 PetscFunctionBegin; 11072 PetscCall(PetscObjectGetComm((PetscObject)A, &comm)); 11073 PetscCallMPI(MPI_Comm_size(comm, &size)); 11074 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 11075 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); 11076 *n = 1; 11077 k = size / N + (size % N > 0); /* There are up to k ranks to a color */ 11078 color = rank / k; 11079 PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm)); 11080 PetscCall(PetscMalloc1(1, iss)); 11081 PetscCall(MatGetOwnershipRange(A, &rstart, &rend)); 11082 PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0])); 11083 PetscCallMPI(MPI_Comm_free(&subcomm)); 11084 PetscFunctionReturn(PETSC_SUCCESS); 11085 } 11086 11087 /*@ 11088 MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection. 11089 11090 If the interpolation and restriction operators are the same, uses `MatPtAP()`. 11091 If they are not the same, uses `MatMatMatMult()`. 11092 11093 Once the coarse grid problem is constructed, correct for interpolation operators 11094 that are not of full rank, which can legitimately happen in the case of non-nested 11095 geometric multigrid. 11096 11097 Input Parameters: 11098 + restrct - restriction operator 11099 . dA - fine grid matrix 11100 . interpolate - interpolation operator 11101 . reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX` 11102 - fill - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate 11103 11104 Output Parameter: 11105 . A - the Galerkin coarse matrix 11106 11107 Options Database Key: 11108 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used 11109 11110 Level: developer 11111 11112 Note: 11113 The deprecated `PETSC_DEFAULT` in `fill` also means use the current value 11114 11115 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()` 11116 @*/ 11117 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) 11118 { 11119 IS zerorows; 11120 Vec diag; 11121 11122 PetscFunctionBegin; 11123 PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported"); 11124 /* Construct the coarse grid matrix */ 11125 if (interpolate == restrct) { 11126 PetscCall(MatPtAP(dA, interpolate, reuse, fill, A)); 11127 } else { 11128 PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A)); 11129 } 11130 11131 /* If the interpolation matrix is not of full rank, A will have zero rows. 11132 This can legitimately happen in the case of non-nested geometric multigrid. 11133 In that event, we set the rows of the matrix to the rows of the identity, 11134 ignoring the equations (as the RHS will also be zero). */ 11135 11136 PetscCall(MatFindZeroRows(*A, &zerorows)); 11137 11138 if (zerorows != NULL) { /* if there are any zero rows */ 11139 PetscCall(MatCreateVecs(*A, &diag, NULL)); 11140 PetscCall(MatGetDiagonal(*A, diag)); 11141 PetscCall(VecISSet(diag, zerorows, 1.0)); 11142 PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES)); 11143 PetscCall(VecDestroy(&diag)); 11144 PetscCall(ISDestroy(&zerorows)); 11145 } 11146 PetscFunctionReturn(PETSC_SUCCESS); 11147 } 11148 11149 /*@C 11150 MatSetOperation - Allows user to set a matrix operation for any matrix type 11151 11152 Logically Collective 11153 11154 Input Parameters: 11155 + mat - the matrix 11156 . op - the name of the operation 11157 - f - the function that provides the operation 11158 11159 Level: developer 11160 11161 Example Usage: 11162 .vb 11163 extern PetscErrorCode usermult(Mat, Vec, Vec); 11164 11165 PetscCall(MatCreateXXX(comm, ..., &A)); 11166 PetscCall(MatSetOperation(A, MATOP_MULT, (PetscErrorCodeFn *)usermult)); 11167 .ve 11168 11169 Notes: 11170 See the file `include/petscmat.h` for a complete list of matrix 11171 operations, which all have the form MATOP_<OPERATION>, where 11172 <OPERATION> is the name (in all capital letters) of the 11173 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11174 11175 All user-provided functions (except for `MATOP_DESTROY`) should have the same calling 11176 sequence as the usual matrix interface routines, since they 11177 are intended to be accessed via the usual matrix interface 11178 routines, e.g., 11179 .vb 11180 MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec) 11181 .ve 11182 11183 In particular each function MUST return `PETSC_SUCCESS` on success and 11184 nonzero on failure. 11185 11186 This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type. 11187 11188 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()` 11189 @*/ 11190 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, PetscErrorCodeFn *f) 11191 { 11192 PetscFunctionBegin; 11193 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11194 if (op == MATOP_VIEW && !mat->ops->viewnative && f != (PetscErrorCodeFn *)mat->ops->view) mat->ops->viewnative = mat->ops->view; 11195 (((PetscErrorCodeFn **)mat->ops)[op]) = f; 11196 PetscFunctionReturn(PETSC_SUCCESS); 11197 } 11198 11199 /*@C 11200 MatGetOperation - Gets a matrix operation for any matrix type. 11201 11202 Not Collective 11203 11204 Input Parameters: 11205 + mat - the matrix 11206 - op - the name of the operation 11207 11208 Output Parameter: 11209 . f - the function that provides the operation 11210 11211 Level: developer 11212 11213 Example Usage: 11214 .vb 11215 PetscErrorCode (*usermult)(Mat, Vec, Vec); 11216 11217 MatGetOperation(A, MATOP_MULT, (PetscErrorCodeFn **)&usermult); 11218 .ve 11219 11220 Notes: 11221 See the file `include/petscmat.h` for a complete list of matrix 11222 operations, which all have the form MATOP_<OPERATION>, where 11223 <OPERATION> is the name (in all capital letters) of the 11224 user interface routine (e.g., `MatMult()` -> `MATOP_MULT`). 11225 11226 This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type. 11227 11228 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()` 11229 @*/ 11230 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, PetscErrorCodeFn **f) 11231 { 11232 PetscFunctionBegin; 11233 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11234 *f = (((PetscErrorCodeFn **)mat->ops)[op]); 11235 PetscFunctionReturn(PETSC_SUCCESS); 11236 } 11237 11238 /*@ 11239 MatHasOperation - Determines whether the given matrix supports the particular operation. 11240 11241 Not Collective 11242 11243 Input Parameters: 11244 + mat - the matrix 11245 - op - the operation, for example, `MATOP_GET_DIAGONAL` 11246 11247 Output Parameter: 11248 . has - either `PETSC_TRUE` or `PETSC_FALSE` 11249 11250 Level: advanced 11251 11252 Note: 11253 See `MatSetOperation()` for additional discussion on naming convention and usage of `op`. 11254 11255 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()` 11256 @*/ 11257 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) 11258 { 11259 PetscFunctionBegin; 11260 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11261 PetscAssertPointer(has, 3); 11262 if (mat->ops->hasoperation) { 11263 PetscUseTypeMethod(mat, hasoperation, op, has); 11264 } else { 11265 if (((void **)mat->ops)[op]) *has = PETSC_TRUE; 11266 else { 11267 *has = PETSC_FALSE; 11268 if (op == MATOP_CREATE_SUBMATRIX) { 11269 PetscMPIInt size; 11270 11271 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size)); 11272 if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has)); 11273 } 11274 } 11275 } 11276 PetscFunctionReturn(PETSC_SUCCESS); 11277 } 11278 11279 /*@ 11280 MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent 11281 11282 Collective 11283 11284 Input Parameter: 11285 . mat - the matrix 11286 11287 Output Parameter: 11288 . cong - either `PETSC_TRUE` or `PETSC_FALSE` 11289 11290 Level: beginner 11291 11292 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout` 11293 @*/ 11294 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) 11295 { 11296 PetscFunctionBegin; 11297 PetscValidHeaderSpecific(mat, MAT_CLASSID, 1); 11298 PetscValidType(mat, 1); 11299 PetscAssertPointer(cong, 2); 11300 if (!mat->rmap || !mat->cmap) { 11301 *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE; 11302 PetscFunctionReturn(PETSC_SUCCESS); 11303 } 11304 if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */ 11305 PetscCall(PetscLayoutSetUp(mat->rmap)); 11306 PetscCall(PetscLayoutSetUp(mat->cmap)); 11307 PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong)); 11308 if (*cong) mat->congruentlayouts = 1; 11309 else mat->congruentlayouts = 0; 11310 } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE; 11311 PetscFunctionReturn(PETSC_SUCCESS); 11312 } 11313 11314 PetscErrorCode MatSetInf(Mat A) 11315 { 11316 PetscFunctionBegin; 11317 PetscUseTypeMethod(A, setinf); 11318 PetscFunctionReturn(PETSC_SUCCESS); 11319 } 11320 11321 /*@ 11322 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 11323 and possibly removes small values from the graph structure. 11324 11325 Collective 11326 11327 Input Parameters: 11328 + A - the matrix 11329 . sym - `PETSC_TRUE` indicates that the graph should be symmetrized 11330 . scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry 11331 . filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value 11332 . num_idx - size of 'index' array 11333 - index - array of block indices to use for graph strength of connection weight 11334 11335 Output Parameter: 11336 . graph - the resulting graph 11337 11338 Level: advanced 11339 11340 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG` 11341 @*/ 11342 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph) 11343 { 11344 PetscFunctionBegin; 11345 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11346 PetscValidType(A, 1); 11347 PetscValidLogicalCollectiveBool(A, scale, 3); 11348 PetscAssertPointer(graph, 7); 11349 PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0)); 11350 PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph); 11351 PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0)); 11352 PetscFunctionReturn(PETSC_SUCCESS); 11353 } 11354 11355 /*@ 11356 MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place, 11357 meaning the same memory is used for the matrix, and no new memory is allocated. 11358 11359 Collective 11360 11361 Input Parameters: 11362 + A - the matrix 11363 - 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 11364 11365 Level: intermediate 11366 11367 Developer Note: 11368 The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end 11369 of the arrays in the data structure are unneeded. 11370 11371 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()` 11372 @*/ 11373 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep) 11374 { 11375 PetscFunctionBegin; 11376 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11377 PetscUseTypeMethod(A, eliminatezeros, keep); 11378 PetscFunctionReturn(PETSC_SUCCESS); 11379 } 11380 11381 /*@C 11382 MatGetCurrentMemType - Get the memory location of the matrix 11383 11384 Not Collective, but the result will be the same on all MPI processes 11385 11386 Input Parameter: 11387 . A - the matrix whose memory type we are checking 11388 11389 Output Parameter: 11390 . m - the memory type 11391 11392 Level: intermediate 11393 11394 .seealso: [](ch_matrices), `Mat`, `MatBoundToCPU()`, `PetscMemType` 11395 @*/ 11396 PetscErrorCode MatGetCurrentMemType(Mat A, PetscMemType *m) 11397 { 11398 PetscFunctionBegin; 11399 PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 11400 PetscAssertPointer(m, 2); 11401 if (A->ops->getcurrentmemtype) PetscUseTypeMethod(A, getcurrentmemtype, m); 11402 else *m = PETSC_MEMTYPE_HOST; 11403 PetscFunctionReturn(PETSC_SUCCESS); 11404 } 11405